From 479db21cdefaf369033e20d26f1fa97ae95c7aa0 Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Wed, 4 Apr 2018 12:51:26 +0200 Subject: [PATCH 001/314] remove sys.path --- doc/conf.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 2dc759c1..03e7eed5 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -37,10 +37,6 @@ #sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, os.path.abspath('../')) - -sys.path - - # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -131,10 +127,6 @@ def setup(app): } - - - - # add RestFull API httpexample_scheme = 'https' From 46fefe78011e2f9d8bd45b7437a4ccef81e44096 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Apr 2018 14:27:03 +0200 Subject: [PATCH 002/314] prepare release0.2 notes --- doc/whatsnew.rst | 1 + doc/whatsnew/v0-2-0.rst | 17 +++++++++++++++++ setup.py | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 doc/whatsnew/v0-2-0.rst diff --git a/doc/whatsnew.rst b/doc/whatsnew.rst index 2542fbc9..4d4eaca0 100644 --- a/doc/whatsnew.rst +++ b/doc/whatsnew.rst @@ -9,5 +9,6 @@ See what's new as per release! :backlinks: top +.. include:: whatsnew/v0-2-0.rst .. include:: whatsnew/v0-1-0.rst .. include:: whatsnew/v0-0-1.rst diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst new file mode 100644 index 00000000..9477834a --- /dev/null +++ b/doc/whatsnew/v0-2-0.rst @@ -0,0 +1,17 @@ +Release v0.2.0 (April 18, 2018) ++++++++++++++++++++++++++++++++ + +The third release of eGo ... +and is still under construction and not ready for a normal use. + + + + +Added features +-------------- + +* + +Notes +----- +* diff --git a/setup.py b/setup.py index afe0df17..2d51320d 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ author='wolfbunke, maltesc', author_email='', description='A python package for distribution and transmission grid analysis and optimization based eDisGo and eTraGo', - version='0.1.0', + version='0.2.0', url='https://github.com/openego/eGo', license="GNU Affero General Public License Version 3 (AGPL-3.0)", packages=find_packages(), From 343574fef64eb42bc4d02a7e7298c5652237106f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Apr 2018 15:28:55 +0200 Subject: [PATCH 003/314] change version --- doc/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 03e7eed5..b0cd619a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -156,9 +156,9 @@ def setup(app): # built documents. # # The short X.Y version. -version = '0.1.0' +version = '0.2' # The full version, including alpha/beta/rc tags. -release = '0.0.1dev' +release = '0.2.0' # The language for content autogenerated by Sphinx. Refer to documentation From 588e9eea84901d1004c2cdbb587c5b2389cda00b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Apr 2018 15:29:23 +0200 Subject: [PATCH 004/314] add change logging --- ego/ego_main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 82164c99..2de67657 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -51,8 +51,10 @@ if __name__ == '__main__': # import scenario settings **args of eTraGo + logging.info('Start calculation') args = get_scenario_setting(json_file='scenario_setting.json') - print (args) + logger.info("calculation settings are used \ + with Metadata: \n %s" %args) try: conn = db.connection(section=args['global']['db']) From 771f14d75894ea195bc1d1a9b7c196dc554fcc62 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Apr 2018 15:36:40 +0200 Subject: [PATCH 005/314] add logger --- ego/tools/io.py | 4 ++++ ego/tools/results.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index b16ed583..08d58fd3 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -24,6 +24,10 @@ import pandas as pd from egoio.tools import db +import logging +logger = logging.getLogger('ego') + + def geolocation_buses(network, session): """ diff --git a/ego/tools/results.py b/ego/tools/results.py index cc55f2c5..af80ab78 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -153,7 +153,7 @@ def __init__(self,eTraGo, scn_name): # add total results here # write_results_to_db(): - + logging.info('Initialisation of eGo Results') pass From 41dd28d9b66080c8ffb5279e33e7815bf8be7cf0 Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Tue, 17 Apr 2018 13:43:19 +0200 Subject: [PATCH 006/314] Update README.rst --- README.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 3e2d816d..2cd70c89 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ .. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 eGo -====== +==== Integrated optimization of flexibility options and grid extension measures for power grids based on eTraGo and eDisGo. @@ -23,7 +23,8 @@ Create a virtualenvironment (where you like it) and activate it: $ virtualenv eGo --clear -p python3.5 $ source venv/bin/activate - $ pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo --process-dependency-links --allow-all-external + $ pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo --process-dependency-links + Copyleft From 2309a07ec09b60ce1837a4efab0e43397029fc7a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 25 May 2018 08:23:06 +0200 Subject: [PATCH 007/314] add new folder and ws notebook --- ego/examples/tutorials/ README.md | 5 + .../etrago_ws_main-checkpoint.ipynb | 736 ++++++++++++++++++ ego/examples/tutorials/etrago_ws_main.ipynb | 736 ++++++++++++++++++ 3 files changed, 1477 insertions(+) create mode 100644 ego/examples/tutorials/ README.md create mode 100644 ego/examples/tutorials/.ipynb_checkpoints/etrago_ws_main-checkpoint.ipynb create mode 100644 ego/examples/tutorials/etrago_ws_main.ipynb diff --git a/ego/examples/tutorials/ README.md b/ego/examples/tutorials/ README.md new file mode 100644 index 00000000..36dc96b6 --- /dev/null +++ b/ego/examples/tutorials/ README.md @@ -0,0 +1,5 @@ +eGo Tutorials +------------- + + + diff --git a/ego/examples/tutorials/.ipynb_checkpoints/etrago_ws_main-checkpoint.ipynb b/ego/examples/tutorials/.ipynb_checkpoints/etrago_ws_main-checkpoint.ipynb new file mode 100644 index 00000000..beb4c795 --- /dev/null +++ b/ego/examples/tutorials/.ipynb_checkpoints/etrago_ws_main-checkpoint.ipynb @@ -0,0 +1,736 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"EUF\"\n", + "\"HSF\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "__copyright__ = \"Zentrum für nachhaltige Energiesysteme Flensburg\"\n", + "__license__ = \"GNU Affero General Public License Version 3 (AGPL-3.0)\"\n", + "__url__ = \"https://github.com/openego/data_processing/blob/master/LICENSE\"\n", + "__author__ = \"wolfbunke, ulfmueller\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "#
EUM Fachtagung 2018 Workshop
\n", + "\n", + "## Optimaler Speicher und Netzausbau in Deutschland mit Hilfe von Open Source Tool bestimmen\n", + "\n", + "****\n", + "\n", + "### Learn more about\n", + "\n", + "\n", + "* __[open_eGo Project Webpage](https://openegoproject.wordpress.com/)__\n", + "* __[eTraGo Tool Documentation](http://etrago.readthedocs.io/en/latest/index.html)__ \n", + "* __[oedb Tutorials](http://oep.iks.cs.ovgu.de/dataedit/)__ How to use the OpenEnergy Database\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"HSF\"\n", + "## Table of Contents \n", + "\n", + "\n", + "* [Getting started with eTraGo](#started)\n", + "* [LOPF Calculation of Germany and neighbours with 10 notes](#d-kmean10)\n", + "* [LOPF Calculation of Schleswig-Holstein](#shcalc)\n", + "* [Using snapshot clustering](#snapshot)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting started with eTraGo \n", + "\n", + "\n", + "The python package eTraGo provides a optimization of flexibility options for transmission grids based on PyPSA. A speciality in this context is that transmission grids are described by the 380, 220 and 110 kV in Germany. Conventionally the 110kV grid is part of the distribution grid. The integration of the transmission and ‘upper’ distribution grid is part of eTraGo.\n", + "\n", + "The focus of optimization are flexibility options with a special focus on energy storages and grid expansion measures.\n", + "\n", + "\n", + "\n", + "\n", + "## Installation \n", + "\n", + "\n", + "The python tool eTraGo can be used in several forms like from a terminal as an execution program, by integrated development environments (IDE) like [Spyder](https://anaconda.org/anaconda/spyder), [Jupyter notebooks](http://jupyter.org/install) or many more.\n", + "\n", + "A description how you to install and work with eTraGo can be found [here](http://etrago.readthedocs.io/en/latest/getting_started.html).\n", + "\n", + "\n", + "\n", + "### Notebook installation\n", + "\n", + "Having Python 3 installed? As eTraGo is designed as a Python package it is mandatory to have Python 3 installed. For this Tutorial we recommend to use an [virtual environment](https://virtualenv.pypa.io/en/stable/installation/). \n", + "See this [tutorial](https://docs.python.org/3/tutorial/venv.html). \n", + "\n", + "If you already have a Python 3 environment you can follow this steps in your terminal:\n", + "\n", + "\n", + "```desktop\n", + "\n", + "$ virtualenv etrago_ws --clear -p python3.5\n", + "$ cd etrago_ws\n", + "$ source bin/activate\n", + "\n", + "$ pip3 install etrago\n", + "$ pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA\n", + "\n", + "$ python3 -m pip install --upgrade pip\n", + "$ python3 -m pip install jupyter\n", + "\n", + "```\n", + "\n", + "### Start you Notebook\n", + "\n", + "```desktop\n", + "$ jupyter notebook\n", + "```\n", + "\n", + "See for more information [how to run your jupyter notebook](https://jupyter.readthedocs.io/en/latest/running.html#running).\n", + "\n", + "\n", + "\n", + "

Warning:

\n", + "For using this Notebook you need an oedb access or a database dump of the input data.
\n", + "

Note:

\n", + "The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/)\n", + "\n", + "## Import eTraGo packages\n", + "\n", + "We are importing the [main function](https://github.com/openego/eTraGo/blob/dev/etrago/appl.py) of eTraGo and its database and plotting functions. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "from numpy import genfromtxt\n", + "np.random.seed()\n", + "import time\n", + "\n", + "import os\n", + "\n", + "if not 'READTHEDOCS' in os.environ:\n", + " # Sphinx does not run this code.\n", + " # Do not import internal packages directly \n", + " from etrago.tools.io import NetworkScenario, results_to_oedb\n", + " from etrago.tools.plot import (plot_line_loading, plot_stacked_gen,\n", + " add_coordinates, curtailment, gen_dist,\n", + " storage_distribution,storage_expansion)\n", + " from etrago.tools.utilities import (load_shedding, data_manipulation_sh,\n", + " results_to_csv, parallelisation, pf_post_lopf, \n", + " loading_minimization, calc_line_losses, group_parallel_lines)\n", + " from etrago.cluster.networkclustering import busmap_from_psql, cluster_on_extra_high_voltage, kmean_clustering\n", + " from egoio.tools import db\n", + " from sqlalchemy.orm import sessionmaker\n", + " from etrago.appl import etrago\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# enable jupyter interactiv plotting\n", + "%matplotlib notebook\n", + "from ipywidgets import *\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# LOPF Calculation of Germany and neighbours with 30 nodes \n", + "\n", + "\n", + "
\n", + "[top](#toc)
\n", + "\n", + "In this section we start our eTraGo calulation with an __Status Quo__ scenario of Germany an its electrical neighbours. For time and performents reasons we are useing the [k-mean](https://de.wikipedia.org/wiki/K-Means-Algorithmus) clustering [functionality of eTraGo](http://etrago.readthedocs.io/en/latest/api/etrago.cluster.html#etrago.cluster.networkclustering.kmean_clustering) and use $k=30$ nodes. For the same reason we choose the time period of __start_snapshot__ and __end_snapshot__ for a day with 24 hours of the scenario year. \n", + "\n", + "\n", + "### Make your calulation settings\n", + "\n", + "A detailed discription of the args python dictionary can be found under . \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "args_k10 = {# Setup and Configuration:\n", + " 'db': 'oedb', # db session\n", + " 'gridversion': \"v0.2.11\", # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", + " 'method': 'lopf', # lopf or pf\n", + " 'pf_post_lopf': False, # state whether you want to perform a pf after a lopf simulation\n", + " 'start_snapshot': 4393, # 2.07.\n", + " 'end_snapshot' : 4400 'scn_name': 'Status Quo', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", + " 'solver': 'glpk', # glpk, cplex or gurobi\n", + " # Export options:\n", + " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", + " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", + " 'export': False, # state if you want to export the results back to the database\n", + " # Settings: \n", + " 'storage_extendable':True, # state if you want storages to be installed at each node if necessary.\n", + " 'generator_noise':True, # state if you want to apply a small generator noise \n", + " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given scenario. \n", + " # if so, provide path, e.g. 'noise_values.csv'\n", + " 'minimize_loading':False,\n", + " # Clustering:\n", + " 'k_mean_clustering': 30, # state if you want to perform a k-means clustering on the given network. \n", + " # State False or the value k (e.g. 20).\n", + " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", + " # Simplifications:\n", + " 'parallelisation':False, # state if you want to run snapshots parallely.\n", + " 'skip_snapshots':False,\n", + " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", + " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", + " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", + " 'comments':None }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Start eTraGo calculation with args setting\n", + "# create network object which incluedes all input and output data\n", + "network = etrago(args_k10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot generation distripution\n", + "gen_dist(network, techs=None, snapshot=1,n_cols=3,gen_size=0.02)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot stacked sum of nominal power for each generator type and timestep\n", + "#fig.set_size_inches(14,14)\n", + "plot_stacked_gen(network, resolution=\"MW\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# make a line loading plot\n", + "# basemade einbauen für hintergrund länder\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(8,8)\n", + "plot_line_loading(network)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot to show extendable storages, if expanded\n", + "storage_expansion(network)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# get storage sizes in MW\n", + "network.storage_units.p_nom_opt.groupby(network.storage_units.carrier, axis=0).sum()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Marginal price per bus node" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# get snapshot\n", + "now = network.snapshots[2]\n", + "\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(6,4)\n", + "\n", + "network.plot(ax=ax,line_widths=pd.Series(0.5,network.lines.index))\n", + "plt.hexbin(network.buses.x, network.buses.y, \n", + " gridsize=20,\n", + " C=network.buses_t.marginal_price.loc[now],\n", + " cmap=plt.cm.jet)\n", + "\n", + "#for some reason the colorbar only works with graphs plt.plot\n", + "#and must be attached plt.colorbar\n", + "\n", + "cb = plt.colorbar()\n", + "cb.set_label('Locational Marginal Price (EUR/MWh)') " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Change the scnario \n", + "\n", + "* Set 'scn_name': to 'NEP 2035' and recalculate. \n", + "\n", + "\n", + "\n", + "****\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# delete eTraGo object\n", + "#del network" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# LOPF Calculation of Schleswig-Holstein \n", + "\n", + "\n", + "
\n", + "[top](#toc)
\n", + "\n", + "\n", + "### Case Schleswig-Holstein\n", + "\n", + "The data set of Schleswing-Holstein is an extract of the main data set and works as an island. The power production and flows of the adjacent network areas are neglected. Therefore, the installed capacity and power production is very high.\n", + "\n", + "For our analysis we used serveral plotting options of eTraGo of [etrago.tools.plot](http://etrago.readthedocs.io/en/latest/api/etrago.tools.html#module-etrago.tools.plot).\n", + "\n", + "\n", + "### Make your settings\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "args_sh = {# Setup and Configuration:\n", + " 'db': 'oedb', # db session\n", + " 'gridversion': None, # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", + " 'method': 'lopf', # lopf or pf\n", + " 'pf_post_lopf': False, # state whether you want to perform a pf after a lopf simulation\n", + " 'start_snapshot': 4393, # 6552\n", + " 'end_snapshot' : 4394,\n", + " 'scn_name': 'SH NEP 2035', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", + " 'solver': 'glpk', # glpk, cplex or gurobi\n", + " # Export options:\n", + " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", + " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", + " 'export': False, # state if you want to export the results back to the database\n", + " # Settings: \n", + " 'storage_extendable':False, # state if you want storages to be installed at each node if necessary.\n", + " 'generator_noise':True, # state if you want to apply a small generator noise \n", + " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given.\n", + " # scenario. if so, provide path, e.g. 'noise_values.csv'\n", + " 'minimize_loading':False,\n", + " # Clustering:\n", + " 'k_mean_clustering': False, # state if you want to perform a k-means clustering on the given network. \n", + " # State False or the value k (e.g. 20).\n", + " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", + " # Simplifications:\n", + " 'parallelisation':False, # state if you want to run snapshots parallely.\n", + " 'skip_snapshots':False,\n", + " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", + " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", + " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", + " 'comments':None }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Start eTraGo calculation with args setting\n", + "# create network object \n", + "network = etrago(args_sh)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot generation distripution\n", + "gen_dist(network, techs=None, snapshot=1,n_cols=3,gen_size=0.02)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot stacked sum of nominal power for each generator type and timestep\n", + "plot_stacked_gen(network, resolution=\"MW\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plots\n", + "# make a line loading plot\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(12,10)\n", + "plot_line_loading(network)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot to show extendable storages\n", + "storage_expansion(network)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# curtailment per carrier / energy source\n", + "curtailment(network, carrier='wind')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# delete network object\n", + "del network" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using pf after lopf Calculation of Germany and neighbours with 30 nodes \n", + "\n", + "
\n", + "[top](#toc)
\n", + "\n", + "\n", + "In order to compute the grid losses we add an power flow calculation after our liniar opf calculation by setting *pf_post_lopf = True*. \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "args_lopf_pf = {# Setup and Configuration:\n", + " 'db': 'oedb', # db session\n", + " 'gridversion': None, # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", + " 'method': 'lopf', # lopf or pf\n", + " 'pf_post_lopf': True, # state whether you want to perform a pf after a lopf simulation\n", + " 'start_snapshot': 4393, \n", + " 'end_snapshot' : 4417,\n", + " 'scn_name': 'NEP 2035', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", + " 'solver': 'glpk', # glpk, cplex or gurobi\n", + " # Export options:\n", + " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", + " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", + " 'export': False, # state if you want to export the results back to the database\n", + " # Settings: \n", + " 'storage_extendable':False, # state if you want storages to be installed at each node if necessary.\n", + " 'generator_noise':True, # state if you want to apply a small generator noise \n", + " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given.\n", + " # scenario. if so, provide path, e.g. 'noise_values.csv'\n", + " 'minimize_loading':False,\n", + " # Clustering:\n", + " 'k_mean_clustering': 30, # state if you want to perform a k-means clustering on the given network. \n", + " # State False or the value k (e.g. 20).\n", + " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", + " # Simplifications:\n", + " 'parallelisation':False, # state if you want to run snapshots parallely.\n", + " 'skip_snapshots':False,\n", + " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", + " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", + " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", + " 'comments':None }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Start eTraGo calculation with args setting\n", + "# create network object\n", + "network = etrago(args_lopf_pf)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot stacked sum of nominal power for each generator type and timestep\n", + "plot_stacked_gen(network, resolution=\"MW\")\n", + "#plt.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plots\n", + "# make a line loading plot\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(8,8)\n", + "\n", + "plot_line_loading(network)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Calculate grid losses\n", + "\n", + "We are using the function [calc_line_losses(network)](http://etrago.readthedocs.io/en/latest/_modules/etrago/tools/utilities.html#calc_line_losses)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "\n", + "# calcualte total grid losses\n", + "calc_line_losses(network)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot line costs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Line losses\n", + "# calculate apparent power S = sqrt(p² + q²) [in MW]\n", + "s0_lines = ((network.lines_t.p0**2 + network.lines_t.q0**2).\\\n", + " apply(np.sqrt)) \n", + "\n", + "# calculate current I = S / U [in A]\n", + "i0_lines = np.multiply(s0_lines, 1000000) / np.multiply(network.lines.v_nom, 1000) \n", + "\n", + "# calculate losses per line and timestep network.lines_t.line_losses = I² * R [in MW]\n", + "network.lines_t.losses = np.divide(i0_lines**2 * network.lines.r, 1000000)\n", + "\n", + "# calculate total losses per line [in MW]\n", + "network.lines = network.lines.assign(losses=np.sum(network.lines_t.losses).values)\n", + "\n", + "# prepare plotting\n", + "timestep =1\n", + "cmap = plt.cm.jet\n", + "\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(6,4)\n", + "\n", + "# do the plotting\n", + "lc= network.plot(line_colors=network.lines.losses, line_cmap=cmap,\n", + " title=\"Line loading\", line_widths=0.55)\n", + "\n", + "cb = plt.colorbar(lc[1])\n", + "cb.set_label('Locational line losses in (EUR/MWh)')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot the reactive power" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# get snapshot\n", + "now = network.snapshots[2]\n", + "#plot the reactive power\n", + "fig,ax = plt.subplots(1,1)\n", + "\n", + "fig.set_size_inches(6,6)\n", + "\n", + "q = network.buses_t.q.sum()#.loc[now]\n", + "\n", + "bus_colors = pd.Series(\"r\",network.buses.index)\n", + "bus_colors[q< 0.] = \"b\"\n", + "\n", + "\n", + "network.plot(bus_sizes=abs(q)*0.005,ax=ax,bus_colors=bus_colors,title=\"Reactive power feed-in (red=+ve, blue=-ve)\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Have a look into the Programm on Github\n", + "\n", + "* " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/ego/examples/tutorials/etrago_ws_main.ipynb b/ego/examples/tutorials/etrago_ws_main.ipynb new file mode 100644 index 00000000..beb4c795 --- /dev/null +++ b/ego/examples/tutorials/etrago_ws_main.ipynb @@ -0,0 +1,736 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"EUF\"\n", + "\"HSF\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "__copyright__ = \"Zentrum für nachhaltige Energiesysteme Flensburg\"\n", + "__license__ = \"GNU Affero General Public License Version 3 (AGPL-3.0)\"\n", + "__url__ = \"https://github.com/openego/data_processing/blob/master/LICENSE\"\n", + "__author__ = \"wolfbunke, ulfmueller\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "#
EUM Fachtagung 2018 Workshop
\n", + "\n", + "## Optimaler Speicher und Netzausbau in Deutschland mit Hilfe von Open Source Tool bestimmen\n", + "\n", + "****\n", + "\n", + "### Learn more about\n", + "\n", + "\n", + "* __[open_eGo Project Webpage](https://openegoproject.wordpress.com/)__\n", + "* __[eTraGo Tool Documentation](http://etrago.readthedocs.io/en/latest/index.html)__ \n", + "* __[oedb Tutorials](http://oep.iks.cs.ovgu.de/dataedit/)__ How to use the OpenEnergy Database\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"HSF\"\n", + "## Table of Contents \n", + "\n", + "\n", + "* [Getting started with eTraGo](#started)\n", + "* [LOPF Calculation of Germany and neighbours with 10 notes](#d-kmean10)\n", + "* [LOPF Calculation of Schleswig-Holstein](#shcalc)\n", + "* [Using snapshot clustering](#snapshot)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting started with eTraGo \n", + "\n", + "\n", + "The python package eTraGo provides a optimization of flexibility options for transmission grids based on PyPSA. A speciality in this context is that transmission grids are described by the 380, 220 and 110 kV in Germany. Conventionally the 110kV grid is part of the distribution grid. The integration of the transmission and ‘upper’ distribution grid is part of eTraGo.\n", + "\n", + "The focus of optimization are flexibility options with a special focus on energy storages and grid expansion measures.\n", + "\n", + "\n", + "\n", + "\n", + "## Installation \n", + "\n", + "\n", + "The python tool eTraGo can be used in several forms like from a terminal as an execution program, by integrated development environments (IDE) like [Spyder](https://anaconda.org/anaconda/spyder), [Jupyter notebooks](http://jupyter.org/install) or many more.\n", + "\n", + "A description how you to install and work with eTraGo can be found [here](http://etrago.readthedocs.io/en/latest/getting_started.html).\n", + "\n", + "\n", + "\n", + "### Notebook installation\n", + "\n", + "Having Python 3 installed? As eTraGo is designed as a Python package it is mandatory to have Python 3 installed. For this Tutorial we recommend to use an [virtual environment](https://virtualenv.pypa.io/en/stable/installation/). \n", + "See this [tutorial](https://docs.python.org/3/tutorial/venv.html). \n", + "\n", + "If you already have a Python 3 environment you can follow this steps in your terminal:\n", + "\n", + "\n", + "```desktop\n", + "\n", + "$ virtualenv etrago_ws --clear -p python3.5\n", + "$ cd etrago_ws\n", + "$ source bin/activate\n", + "\n", + "$ pip3 install etrago\n", + "$ pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA\n", + "\n", + "$ python3 -m pip install --upgrade pip\n", + "$ python3 -m pip install jupyter\n", + "\n", + "```\n", + "\n", + "### Start you Notebook\n", + "\n", + "```desktop\n", + "$ jupyter notebook\n", + "```\n", + "\n", + "See for more information [how to run your jupyter notebook](https://jupyter.readthedocs.io/en/latest/running.html#running).\n", + "\n", + "\n", + "\n", + "

Warning:

\n", + "For using this Notebook you need an oedb access or a database dump of the input data.
\n", + "

Note:

\n", + "The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/)\n", + "\n", + "## Import eTraGo packages\n", + "\n", + "We are importing the [main function](https://github.com/openego/eTraGo/blob/dev/etrago/appl.py) of eTraGo and its database and plotting functions. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "from numpy import genfromtxt\n", + "np.random.seed()\n", + "import time\n", + "\n", + "import os\n", + "\n", + "if not 'READTHEDOCS' in os.environ:\n", + " # Sphinx does not run this code.\n", + " # Do not import internal packages directly \n", + " from etrago.tools.io import NetworkScenario, results_to_oedb\n", + " from etrago.tools.plot import (plot_line_loading, plot_stacked_gen,\n", + " add_coordinates, curtailment, gen_dist,\n", + " storage_distribution,storage_expansion)\n", + " from etrago.tools.utilities import (load_shedding, data_manipulation_sh,\n", + " results_to_csv, parallelisation, pf_post_lopf, \n", + " loading_minimization, calc_line_losses, group_parallel_lines)\n", + " from etrago.cluster.networkclustering import busmap_from_psql, cluster_on_extra_high_voltage, kmean_clustering\n", + " from egoio.tools import db\n", + " from sqlalchemy.orm import sessionmaker\n", + " from etrago.appl import etrago\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# enable jupyter interactiv plotting\n", + "%matplotlib notebook\n", + "from ipywidgets import *\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# LOPF Calculation of Germany and neighbours with 30 nodes \n", + "\n", + "\n", + "
\n", + "[top](#toc)
\n", + "\n", + "In this section we start our eTraGo calulation with an __Status Quo__ scenario of Germany an its electrical neighbours. For time and performents reasons we are useing the [k-mean](https://de.wikipedia.org/wiki/K-Means-Algorithmus) clustering [functionality of eTraGo](http://etrago.readthedocs.io/en/latest/api/etrago.cluster.html#etrago.cluster.networkclustering.kmean_clustering) and use $k=30$ nodes. For the same reason we choose the time period of __start_snapshot__ and __end_snapshot__ for a day with 24 hours of the scenario year. \n", + "\n", + "\n", + "### Make your calulation settings\n", + "\n", + "A detailed discription of the args python dictionary can be found under . \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "args_k10 = {# Setup and Configuration:\n", + " 'db': 'oedb', # db session\n", + " 'gridversion': \"v0.2.11\", # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", + " 'method': 'lopf', # lopf or pf\n", + " 'pf_post_lopf': False, # state whether you want to perform a pf after a lopf simulation\n", + " 'start_snapshot': 4393, # 2.07.\n", + " 'end_snapshot' : 4400 'scn_name': 'Status Quo', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", + " 'solver': 'glpk', # glpk, cplex or gurobi\n", + " # Export options:\n", + " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", + " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", + " 'export': False, # state if you want to export the results back to the database\n", + " # Settings: \n", + " 'storage_extendable':True, # state if you want storages to be installed at each node if necessary.\n", + " 'generator_noise':True, # state if you want to apply a small generator noise \n", + " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given scenario. \n", + " # if so, provide path, e.g. 'noise_values.csv'\n", + " 'minimize_loading':False,\n", + " # Clustering:\n", + " 'k_mean_clustering': 30, # state if you want to perform a k-means clustering on the given network. \n", + " # State False or the value k (e.g. 20).\n", + " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", + " # Simplifications:\n", + " 'parallelisation':False, # state if you want to run snapshots parallely.\n", + " 'skip_snapshots':False,\n", + " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", + " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", + " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", + " 'comments':None }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Start eTraGo calculation with args setting\n", + "# create network object which incluedes all input and output data\n", + "network = etrago(args_k10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot generation distripution\n", + "gen_dist(network, techs=None, snapshot=1,n_cols=3,gen_size=0.02)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot stacked sum of nominal power for each generator type and timestep\n", + "#fig.set_size_inches(14,14)\n", + "plot_stacked_gen(network, resolution=\"MW\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# make a line loading plot\n", + "# basemade einbauen für hintergrund länder\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(8,8)\n", + "plot_line_loading(network)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot to show extendable storages, if expanded\n", + "storage_expansion(network)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# get storage sizes in MW\n", + "network.storage_units.p_nom_opt.groupby(network.storage_units.carrier, axis=0).sum()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Marginal price per bus node" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# get snapshot\n", + "now = network.snapshots[2]\n", + "\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(6,4)\n", + "\n", + "network.plot(ax=ax,line_widths=pd.Series(0.5,network.lines.index))\n", + "plt.hexbin(network.buses.x, network.buses.y, \n", + " gridsize=20,\n", + " C=network.buses_t.marginal_price.loc[now],\n", + " cmap=plt.cm.jet)\n", + "\n", + "#for some reason the colorbar only works with graphs plt.plot\n", + "#and must be attached plt.colorbar\n", + "\n", + "cb = plt.colorbar()\n", + "cb.set_label('Locational Marginal Price (EUR/MWh)') " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Change the scnario \n", + "\n", + "* Set 'scn_name': to 'NEP 2035' and recalculate. \n", + "\n", + "\n", + "\n", + "****\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# delete eTraGo object\n", + "#del network" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# LOPF Calculation of Schleswig-Holstein \n", + "\n", + "\n", + "
\n", + "[top](#toc)
\n", + "\n", + "\n", + "### Case Schleswig-Holstein\n", + "\n", + "The data set of Schleswing-Holstein is an extract of the main data set and works as an island. The power production and flows of the adjacent network areas are neglected. Therefore, the installed capacity and power production is very high.\n", + "\n", + "For our analysis we used serveral plotting options of eTraGo of [etrago.tools.plot](http://etrago.readthedocs.io/en/latest/api/etrago.tools.html#module-etrago.tools.plot).\n", + "\n", + "\n", + "### Make your settings\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "args_sh = {# Setup and Configuration:\n", + " 'db': 'oedb', # db session\n", + " 'gridversion': None, # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", + " 'method': 'lopf', # lopf or pf\n", + " 'pf_post_lopf': False, # state whether you want to perform a pf after a lopf simulation\n", + " 'start_snapshot': 4393, # 6552\n", + " 'end_snapshot' : 4394,\n", + " 'scn_name': 'SH NEP 2035', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", + " 'solver': 'glpk', # glpk, cplex or gurobi\n", + " # Export options:\n", + " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", + " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", + " 'export': False, # state if you want to export the results back to the database\n", + " # Settings: \n", + " 'storage_extendable':False, # state if you want storages to be installed at each node if necessary.\n", + " 'generator_noise':True, # state if you want to apply a small generator noise \n", + " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given.\n", + " # scenario. if so, provide path, e.g. 'noise_values.csv'\n", + " 'minimize_loading':False,\n", + " # Clustering:\n", + " 'k_mean_clustering': False, # state if you want to perform a k-means clustering on the given network. \n", + " # State False or the value k (e.g. 20).\n", + " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", + " # Simplifications:\n", + " 'parallelisation':False, # state if you want to run snapshots parallely.\n", + " 'skip_snapshots':False,\n", + " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", + " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", + " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", + " 'comments':None }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Start eTraGo calculation with args setting\n", + "# create network object \n", + "network = etrago(args_sh)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot generation distripution\n", + "gen_dist(network, techs=None, snapshot=1,n_cols=3,gen_size=0.02)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot stacked sum of nominal power for each generator type and timestep\n", + "plot_stacked_gen(network, resolution=\"MW\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plots\n", + "# make a line loading plot\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(12,10)\n", + "plot_line_loading(network)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot to show extendable storages\n", + "storage_expansion(network)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# curtailment per carrier / energy source\n", + "curtailment(network, carrier='wind')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# delete network object\n", + "del network" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using pf after lopf Calculation of Germany and neighbours with 30 nodes \n", + "\n", + "
\n", + "[top](#toc)
\n", + "\n", + "\n", + "In order to compute the grid losses we add an power flow calculation after our liniar opf calculation by setting *pf_post_lopf = True*. \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "args_lopf_pf = {# Setup and Configuration:\n", + " 'db': 'oedb', # db session\n", + " 'gridversion': None, # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", + " 'method': 'lopf', # lopf or pf\n", + " 'pf_post_lopf': True, # state whether you want to perform a pf after a lopf simulation\n", + " 'start_snapshot': 4393, \n", + " 'end_snapshot' : 4417,\n", + " 'scn_name': 'NEP 2035', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", + " 'solver': 'glpk', # glpk, cplex or gurobi\n", + " # Export options:\n", + " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", + " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", + " 'export': False, # state if you want to export the results back to the database\n", + " # Settings: \n", + " 'storage_extendable':False, # state if you want storages to be installed at each node if necessary.\n", + " 'generator_noise':True, # state if you want to apply a small generator noise \n", + " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given.\n", + " # scenario. if so, provide path, e.g. 'noise_values.csv'\n", + " 'minimize_loading':False,\n", + " # Clustering:\n", + " 'k_mean_clustering': 30, # state if you want to perform a k-means clustering on the given network. \n", + " # State False or the value k (e.g. 20).\n", + " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", + " # Simplifications:\n", + " 'parallelisation':False, # state if you want to run snapshots parallely.\n", + " 'skip_snapshots':False,\n", + " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", + " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", + " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", + " 'comments':None }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Start eTraGo calculation with args setting\n", + "# create network object\n", + "network = etrago(args_lopf_pf)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plot stacked sum of nominal power for each generator type and timestep\n", + "plot_stacked_gen(network, resolution=\"MW\")\n", + "#plt.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# plots\n", + "# make a line loading plot\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(8,8)\n", + "\n", + "plot_line_loading(network)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Calculate grid losses\n", + "\n", + "We are using the function [calc_line_losses(network)](http://etrago.readthedocs.io/en/latest/_modules/etrago/tools/utilities.html#calc_line_losses)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "\n", + "# calcualte total grid losses\n", + "calc_line_losses(network)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot line costs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Line losses\n", + "# calculate apparent power S = sqrt(p² + q²) [in MW]\n", + "s0_lines = ((network.lines_t.p0**2 + network.lines_t.q0**2).\\\n", + " apply(np.sqrt)) \n", + "\n", + "# calculate current I = S / U [in A]\n", + "i0_lines = np.multiply(s0_lines, 1000000) / np.multiply(network.lines.v_nom, 1000) \n", + "\n", + "# calculate losses per line and timestep network.lines_t.line_losses = I² * R [in MW]\n", + "network.lines_t.losses = np.divide(i0_lines**2 * network.lines.r, 1000000)\n", + "\n", + "# calculate total losses per line [in MW]\n", + "network.lines = network.lines.assign(losses=np.sum(network.lines_t.losses).values)\n", + "\n", + "# prepare plotting\n", + "timestep =1\n", + "cmap = plt.cm.jet\n", + "\n", + "fig,ax = plt.subplots(1,1)\n", + "fig.set_size_inches(6,4)\n", + "\n", + "# do the plotting\n", + "lc= network.plot(line_colors=network.lines.losses, line_cmap=cmap,\n", + " title=\"Line loading\", line_widths=0.55)\n", + "\n", + "cb = plt.colorbar(lc[1])\n", + "cb.set_label('Locational line losses in (EUR/MWh)')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot the reactive power" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# get snapshot\n", + "now = network.snapshots[2]\n", + "#plot the reactive power\n", + "fig,ax = plt.subplots(1,1)\n", + "\n", + "fig.set_size_inches(6,6)\n", + "\n", + "q = network.buses_t.q.sum()#.loc[now]\n", + "\n", + "bus_colors = pd.Series(\"r\",network.buses.index)\n", + "bus_colors[q< 0.] = \"b\"\n", + "\n", + "\n", + "network.plot(bus_sizes=abs(q)*0.005,ax=ax,bus_colors=bus_colors,title=\"Reactive power feed-in (red=+ve, blue=-ve)\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Have a look into the Programm on Github\n", + "\n", + "* " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From b7494866d212acb5a4f8347552b93f59547ca5e7 Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Fri, 25 May 2018 08:26:11 +0200 Subject: [PATCH 008/314] Delete etrago_ws_main-checkpoint.ipynb --- .../etrago_ws_main-checkpoint.ipynb | 736 ------------------ 1 file changed, 736 deletions(-) delete mode 100644 ego/examples/tutorials/.ipynb_checkpoints/etrago_ws_main-checkpoint.ipynb diff --git a/ego/examples/tutorials/.ipynb_checkpoints/etrago_ws_main-checkpoint.ipynb b/ego/examples/tutorials/.ipynb_checkpoints/etrago_ws_main-checkpoint.ipynb deleted file mode 100644 index beb4c795..00000000 --- a/ego/examples/tutorials/.ipynb_checkpoints/etrago_ws_main-checkpoint.ipynb +++ /dev/null @@ -1,736 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\"EUF\"\n", - "\"HSF\"\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "__copyright__ = \"Zentrum für nachhaltige Energiesysteme Flensburg\"\n", - "__license__ = \"GNU Affero General Public License Version 3 (AGPL-3.0)\"\n", - "__url__ = \"https://github.com/openego/data_processing/blob/master/LICENSE\"\n", - "__author__ = \"wolfbunke, ulfmueller\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "#
EUM Fachtagung 2018 Workshop
\n", - "\n", - "## Optimaler Speicher und Netzausbau in Deutschland mit Hilfe von Open Source Tool bestimmen\n", - "\n", - "****\n", - "\n", - "### Learn more about\n", - "\n", - "\n", - "* __[open_eGo Project Webpage](https://openegoproject.wordpress.com/)__\n", - "* __[eTraGo Tool Documentation](http://etrago.readthedocs.io/en/latest/index.html)__ \n", - "* __[oedb Tutorials](http://oep.iks.cs.ovgu.de/dataedit/)__ How to use the OpenEnergy Database\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\"HSF\"\n", - "## Table of Contents \n", - "\n", - "\n", - "* [Getting started with eTraGo](#started)\n", - "* [LOPF Calculation of Germany and neighbours with 10 notes](#d-kmean10)\n", - "* [LOPF Calculation of Schleswig-Holstein](#shcalc)\n", - "* [Using snapshot clustering](#snapshot)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Getting started with eTraGo \n", - "\n", - "\n", - "The python package eTraGo provides a optimization of flexibility options for transmission grids based on PyPSA. A speciality in this context is that transmission grids are described by the 380, 220 and 110 kV in Germany. Conventionally the 110kV grid is part of the distribution grid. The integration of the transmission and ‘upper’ distribution grid is part of eTraGo.\n", - "\n", - "The focus of optimization are flexibility options with a special focus on energy storages and grid expansion measures.\n", - "\n", - "\n", - "\n", - "\n", - "## Installation \n", - "\n", - "\n", - "The python tool eTraGo can be used in several forms like from a terminal as an execution program, by integrated development environments (IDE) like [Spyder](https://anaconda.org/anaconda/spyder), [Jupyter notebooks](http://jupyter.org/install) or many more.\n", - "\n", - "A description how you to install and work with eTraGo can be found [here](http://etrago.readthedocs.io/en/latest/getting_started.html).\n", - "\n", - "\n", - "\n", - "### Notebook installation\n", - "\n", - "Having Python 3 installed? As eTraGo is designed as a Python package it is mandatory to have Python 3 installed. For this Tutorial we recommend to use an [virtual environment](https://virtualenv.pypa.io/en/stable/installation/). \n", - "See this [tutorial](https://docs.python.org/3/tutorial/venv.html). \n", - "\n", - "If you already have a Python 3 environment you can follow this steps in your terminal:\n", - "\n", - "\n", - "```desktop\n", - "\n", - "$ virtualenv etrago_ws --clear -p python3.5\n", - "$ cd etrago_ws\n", - "$ source bin/activate\n", - "\n", - "$ pip3 install etrago\n", - "$ pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA\n", - "\n", - "$ python3 -m pip install --upgrade pip\n", - "$ python3 -m pip install jupyter\n", - "\n", - "```\n", - "\n", - "### Start you Notebook\n", - "\n", - "```desktop\n", - "$ jupyter notebook\n", - "```\n", - "\n", - "See for more information [how to run your jupyter notebook](https://jupyter.readthedocs.io/en/latest/running.html#running).\n", - "\n", - "\n", - "\n", - "

Warning:

\n", - "For using this Notebook you need an oedb access or a database dump of the input data.
\n", - "

Note:

\n", - "The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/)\n", - "\n", - "## Import eTraGo packages\n", - "\n", - "We are importing the [main function](https://github.com/openego/eTraGo/blob/dev/etrago/appl.py) of eTraGo and its database and plotting functions. \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "from numpy import genfromtxt\n", - "np.random.seed()\n", - "import time\n", - "\n", - "import os\n", - "\n", - "if not 'READTHEDOCS' in os.environ:\n", - " # Sphinx does not run this code.\n", - " # Do not import internal packages directly \n", - " from etrago.tools.io import NetworkScenario, results_to_oedb\n", - " from etrago.tools.plot import (plot_line_loading, plot_stacked_gen,\n", - " add_coordinates, curtailment, gen_dist,\n", - " storage_distribution,storage_expansion)\n", - " from etrago.tools.utilities import (load_shedding, data_manipulation_sh,\n", - " results_to_csv, parallelisation, pf_post_lopf, \n", - " loading_minimization, calc_line_losses, group_parallel_lines)\n", - " from etrago.cluster.networkclustering import busmap_from_psql, cluster_on_extra_high_voltage, kmean_clustering\n", - " from egoio.tools import db\n", - " from sqlalchemy.orm import sessionmaker\n", - " from etrago.appl import etrago\n", - " \n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# enable jupyter interactiv plotting\n", - "%matplotlib notebook\n", - "from ipywidgets import *\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# LOPF Calculation of Germany and neighbours with 30 nodes \n", - "\n", - "\n", - "
\n", - "[top](#toc)
\n", - "\n", - "In this section we start our eTraGo calulation with an __Status Quo__ scenario of Germany an its electrical neighbours. For time and performents reasons we are useing the [k-mean](https://de.wikipedia.org/wiki/K-Means-Algorithmus) clustering [functionality of eTraGo](http://etrago.readthedocs.io/en/latest/api/etrago.cluster.html#etrago.cluster.networkclustering.kmean_clustering) and use $k=30$ nodes. For the same reason we choose the time period of __start_snapshot__ and __end_snapshot__ for a day with 24 hours of the scenario year. \n", - "\n", - "\n", - "### Make your calulation settings\n", - "\n", - "A detailed discription of the args python dictionary can be found under . \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "args_k10 = {# Setup and Configuration:\n", - " 'db': 'oedb', # db session\n", - " 'gridversion': \"v0.2.11\", # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", - " 'method': 'lopf', # lopf or pf\n", - " 'pf_post_lopf': False, # state whether you want to perform a pf after a lopf simulation\n", - " 'start_snapshot': 4393, # 2.07.\n", - " 'end_snapshot' : 4400 'scn_name': 'Status Quo', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", - " 'solver': 'glpk', # glpk, cplex or gurobi\n", - " # Export options:\n", - " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", - " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", - " 'export': False, # state if you want to export the results back to the database\n", - " # Settings: \n", - " 'storage_extendable':True, # state if you want storages to be installed at each node if necessary.\n", - " 'generator_noise':True, # state if you want to apply a small generator noise \n", - " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given scenario. \n", - " # if so, provide path, e.g. 'noise_values.csv'\n", - " 'minimize_loading':False,\n", - " # Clustering:\n", - " 'k_mean_clustering': 30, # state if you want to perform a k-means clustering on the given network. \n", - " # State False or the value k (e.g. 20).\n", - " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", - " # Simplifications:\n", - " 'parallelisation':False, # state if you want to run snapshots parallely.\n", - " 'skip_snapshots':False,\n", - " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", - " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", - " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", - " 'comments':None }" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Start eTraGo calculation with args setting\n", - "# create network object which incluedes all input and output data\n", - "network = etrago(args_k10)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plot generation distripution\n", - "gen_dist(network, techs=None, snapshot=1,n_cols=3,gen_size=0.02)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plot stacked sum of nominal power for each generator type and timestep\n", - "#fig.set_size_inches(14,14)\n", - "plot_stacked_gen(network, resolution=\"MW\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# make a line loading plot\n", - "# basemade einbauen für hintergrund länder\n", - "fig,ax = plt.subplots(1,1)\n", - "fig.set_size_inches(8,8)\n", - "plot_line_loading(network)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plot to show extendable storages, if expanded\n", - "storage_expansion(network)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# get storage sizes in MW\n", - "network.storage_units.p_nom_opt.groupby(network.storage_units.carrier, axis=0).sum()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Marginal price per bus node" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# get snapshot\n", - "now = network.snapshots[2]\n", - "\n", - "fig,ax = plt.subplots(1,1)\n", - "fig.set_size_inches(6,4)\n", - "\n", - "network.plot(ax=ax,line_widths=pd.Series(0.5,network.lines.index))\n", - "plt.hexbin(network.buses.x, network.buses.y, \n", - " gridsize=20,\n", - " C=network.buses_t.marginal_price.loc[now],\n", - " cmap=plt.cm.jet)\n", - "\n", - "#for some reason the colorbar only works with graphs plt.plot\n", - "#and must be attached plt.colorbar\n", - "\n", - "cb = plt.colorbar()\n", - "cb.set_label('Locational Marginal Price (EUR/MWh)') " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Change the scnario \n", - "\n", - "* Set 'scn_name': to 'NEP 2035' and recalculate. \n", - "\n", - "\n", - "\n", - "****\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# delete eTraGo object\n", - "#del network" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# LOPF Calculation of Schleswig-Holstein \n", - "\n", - "\n", - "
\n", - "[top](#toc)
\n", - "\n", - "\n", - "### Case Schleswig-Holstein\n", - "\n", - "The data set of Schleswing-Holstein is an extract of the main data set and works as an island. The power production and flows of the adjacent network areas are neglected. Therefore, the installed capacity and power production is very high.\n", - "\n", - "For our analysis we used serveral plotting options of eTraGo of [etrago.tools.plot](http://etrago.readthedocs.io/en/latest/api/etrago.tools.html#module-etrago.tools.plot).\n", - "\n", - "\n", - "### Make your settings\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "args_sh = {# Setup and Configuration:\n", - " 'db': 'oedb', # db session\n", - " 'gridversion': None, # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", - " 'method': 'lopf', # lopf or pf\n", - " 'pf_post_lopf': False, # state whether you want to perform a pf after a lopf simulation\n", - " 'start_snapshot': 4393, # 6552\n", - " 'end_snapshot' : 4394,\n", - " 'scn_name': 'SH NEP 2035', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", - " 'solver': 'glpk', # glpk, cplex or gurobi\n", - " # Export options:\n", - " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", - " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", - " 'export': False, # state if you want to export the results back to the database\n", - " # Settings: \n", - " 'storage_extendable':False, # state if you want storages to be installed at each node if necessary.\n", - " 'generator_noise':True, # state if you want to apply a small generator noise \n", - " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given.\n", - " # scenario. if so, provide path, e.g. 'noise_values.csv'\n", - " 'minimize_loading':False,\n", - " # Clustering:\n", - " 'k_mean_clustering': False, # state if you want to perform a k-means clustering on the given network. \n", - " # State False or the value k (e.g. 20).\n", - " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", - " # Simplifications:\n", - " 'parallelisation':False, # state if you want to run snapshots parallely.\n", - " 'skip_snapshots':False,\n", - " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", - " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", - " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", - " 'comments':None }" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Start eTraGo calculation with args setting\n", - "# create network object \n", - "network = etrago(args_sh)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plot generation distripution\n", - "gen_dist(network, techs=None, snapshot=1,n_cols=3,gen_size=0.02)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plot stacked sum of nominal power for each generator type and timestep\n", - "plot_stacked_gen(network, resolution=\"MW\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plots\n", - "# make a line loading plot\n", - "fig,ax = plt.subplots(1,1)\n", - "fig.set_size_inches(12,10)\n", - "plot_line_loading(network)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plot to show extendable storages\n", - "storage_expansion(network)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# curtailment per carrier / energy source\n", - "curtailment(network, carrier='wind')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# delete network object\n", - "del network" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Using pf after lopf Calculation of Germany and neighbours with 30 nodes \n", - "\n", - "
\n", - "[top](#toc)
\n", - "\n", - "\n", - "In order to compute the grid losses we add an power flow calculation after our liniar opf calculation by setting *pf_post_lopf = True*. \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "args_lopf_pf = {# Setup and Configuration:\n", - " 'db': 'oedb', # db session\n", - " 'gridversion': None, # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", - " 'method': 'lopf', # lopf or pf\n", - " 'pf_post_lopf': True, # state whether you want to perform a pf after a lopf simulation\n", - " 'start_snapshot': 4393, \n", - " 'end_snapshot' : 4417,\n", - " 'scn_name': 'NEP 2035', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", - " 'solver': 'glpk', # glpk, cplex or gurobi\n", - " # Export options:\n", - " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", - " 'results': False, # state if and where you want to save results as csv: False or /path/tofolder\n", - " 'export': False, # state if you want to export the results back to the database\n", - " # Settings: \n", - " 'storage_extendable':False, # state if you want storages to be installed at each node if necessary.\n", - " 'generator_noise':True, # state if you want to apply a small generator noise \n", - " 'reproduce_noise': False, # state if you want to use a predefined set of random noise for the given.\n", - " # scenario. if so, provide path, e.g. 'noise_values.csv'\n", - " 'minimize_loading':False,\n", - " # Clustering:\n", - " 'k_mean_clustering': 30, # state if you want to perform a k-means clustering on the given network. \n", - " # State False or the value k (e.g. 20).\n", - " 'network_clustering': False, # state if you want to perform a clustering of HV buses to EHV buses.\n", - " # Simplifications:\n", - " 'parallelisation':False, # state if you want to run snapshots parallely.\n", - " 'skip_snapshots':False,\n", - " 'line_grouping': False, # state if you want to group lines running between the same buses.\n", - " 'branch_capacity_factor': 0.7, # globally extend or lower branch capacities\n", - " 'load_shedding':False, # meet the demand at very high cost; for debugging purposes.\n", - " 'comments':None }" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Start eTraGo calculation with args setting\n", - "# create network object\n", - "network = etrago(args_lopf_pf)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plot stacked sum of nominal power for each generator type and timestep\n", - "plot_stacked_gen(network, resolution=\"MW\")\n", - "#plt.close()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# plots\n", - "# make a line loading plot\n", - "fig,ax = plt.subplots(1,1)\n", - "fig.set_size_inches(8,8)\n", - "\n", - "plot_line_loading(network)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Calculate grid losses\n", - "\n", - "We are using the function [calc_line_losses(network)](http://etrago.readthedocs.io/en/latest/_modules/etrago/tools/utilities.html#calc_line_losses)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "\n", - "# calcualte total grid losses\n", - "calc_line_losses(network)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plot line costs" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Line losses\n", - "# calculate apparent power S = sqrt(p² + q²) [in MW]\n", - "s0_lines = ((network.lines_t.p0**2 + network.lines_t.q0**2).\\\n", - " apply(np.sqrt)) \n", - "\n", - "# calculate current I = S / U [in A]\n", - "i0_lines = np.multiply(s0_lines, 1000000) / np.multiply(network.lines.v_nom, 1000) \n", - "\n", - "# calculate losses per line and timestep network.lines_t.line_losses = I² * R [in MW]\n", - "network.lines_t.losses = np.divide(i0_lines**2 * network.lines.r, 1000000)\n", - "\n", - "# calculate total losses per line [in MW]\n", - "network.lines = network.lines.assign(losses=np.sum(network.lines_t.losses).values)\n", - "\n", - "# prepare plotting\n", - "timestep =1\n", - "cmap = plt.cm.jet\n", - "\n", - "fig,ax = plt.subplots(1,1)\n", - "fig.set_size_inches(6,4)\n", - "\n", - "# do the plotting\n", - "lc= network.plot(line_colors=network.lines.losses, line_cmap=cmap,\n", - " title=\"Line loading\", line_widths=0.55)\n", - "\n", - "cb = plt.colorbar(lc[1])\n", - "cb.set_label('Locational line losses in (EUR/MWh)')\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plot the reactive power" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# get snapshot\n", - "now = network.snapshots[2]\n", - "#plot the reactive power\n", - "fig,ax = plt.subplots(1,1)\n", - "\n", - "fig.set_size_inches(6,6)\n", - "\n", - "q = network.buses_t.q.sum()#.loc[now]\n", - "\n", - "bus_colors = pd.Series(\"r\",network.buses.index)\n", - "bus_colors[q< 0.] = \"b\"\n", - "\n", - "\n", - "network.plot(bus_sizes=abs(q)*0.005,ax=ax,bus_colors=bus_colors,title=\"Reactive power feed-in (red=+ve, blue=-ve)\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Have a look into the Programm on Github\n", - "\n", - "* " - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From efa1ce216273e4574d9634c3fdac895dde67693c Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Fri, 25 May 2018 08:27:48 +0200 Subject: [PATCH 009/314] add jupyter checkpoints --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 738b62ef..02c1d0f0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ ego/scenario_setting.json ego/noise_values.csv .idea/ noise_values.csv - +.ipynb_checkpoints From 7aee221157783328d289190a57cd2930439ed9cf Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Fri, 25 May 2018 08:36:04 +0200 Subject: [PATCH 010/314] add installation description --- ego/examples/tutorials/ README.md | 5 --- ego/examples/tutorials/README.md | 60 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) delete mode 100644 ego/examples/tutorials/ README.md create mode 100644 ego/examples/tutorials/README.md diff --git a/ego/examples/tutorials/ README.md b/ego/examples/tutorials/ README.md deleted file mode 100644 index 36dc96b6..00000000 --- a/ego/examples/tutorials/ README.md +++ /dev/null @@ -1,5 +0,0 @@ -eGo Tutorials -------------- - - - diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md new file mode 100644 index 00000000..5b1720cb --- /dev/null +++ b/ego/examples/tutorials/README.md @@ -0,0 +1,60 @@ +eGo Tutorials +------------- + + + + +## Installation + + +### eDisGo + +### eTraGo + +The python tool eTraGo can be used in several forms like from a terminal as an execution program, by integrated development environments (IDE) like [Spyder](https://anaconda.org/anaconda/spyder), [Jupyter notebooks](http://jupyter.org/install) or many more. + +A description how you to install and work with eTraGo can be found [here](http://etrago.readthedocs.io/en/latest/getting_started.html). + + +### Notebook installation + +Having Python 3 installed? As eGo is designed as a Python package it is mandatory to have Python 3 installed. For this Tutorial we recommend to use an [virtual environment](https://virtualenv.pypa.io/en/stable/installation/). +See this [tutorial](https://docs.python.org/3/tutorial/venv.html). + +If you already have a Python 3 environment you can follow this steps in your terminal: + + +```desktop + +$ virtualenv ego_tutorial --clear -p python3.5 +$ cd ego_tutorial +$ source bin/activate + +$ pip3 install etrago==0.5.1 +$ pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA + +$ python3 -m pip install --upgrade pip +$ python3 -m pip install jupyter + +``` + +### Start you Notebook + +```desktop +$ jupyter notebook +``` + +See for more information [how to run your jupyter notebook](https://jupyter.readthedocs.io/en/latest/running.html#running). + + + +

Warning:

+For using this Notebook you need an oedb access or a database dump of the input data.
+

Note:

+The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/) + +## Import eTraGo packages + +We are importing the [main function](https://github.com/openego/eTraGo/blob/dev/etrago/appl.py) of eTraGo and its database and plotting functions. + + From dffdf5949709d93e80218b27fb52916e99fb872d Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Fri, 25 May 2018 08:42:59 +0200 Subject: [PATCH 011/314] Rename etrago_ws_main.ipynb to etrago_ws_eum-fachtagung.ipynb --- .../{etrago_ws_main.ipynb => etrago_ws_eum-fachtagung.ipynb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ego/examples/tutorials/{etrago_ws_main.ipynb => etrago_ws_eum-fachtagung.ipynb} (100%) diff --git a/ego/examples/tutorials/etrago_ws_main.ipynb b/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb similarity index 100% rename from ego/examples/tutorials/etrago_ws_main.ipynb rename to ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb From 1e92b08f426db4a4f998fca2de2a5f62c907aa60 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 25 May 2018 13:30:35 +0200 Subject: [PATCH 012/314] add changes --- ego/examples/tutorials/etrago_ws_main.ipynb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ego/examples/tutorials/etrago_ws_main.ipynb b/ego/examples/tutorials/etrago_ws_main.ipynb index beb4c795..30686a5a 100644 --- a/ego/examples/tutorials/etrago_ws_main.ipynb +++ b/ego/examples/tutorials/etrago_ws_main.ipynb @@ -123,7 +123,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "import numpy as np\n", @@ -189,7 +191,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "args_k10 = {# Setup and Configuration:\n", @@ -226,7 +230,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", From d4f88349cc6076c0cfcb49617c34bb2446104e9f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 4 Jun 2018 12:23:27 +0200 Subject: [PATCH 013/314] remove installation text to readme --- .../tutorials/etrago_ws_eum-fachtagung.ipynb | 64 +++---------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb b/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb index 30686a5a..18f659f0 100644 --- a/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb +++ b/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb @@ -27,9 +27,9 @@ "metadata": {}, "source": [ "\n", - "#
EUM Fachtagung 2018 Workshop
\n", + "#
OpenMod 2018 Workshop Zürich
\n", "\n", - "## Optimaler Speicher und Netzausbau in Deutschland mit Hilfe von Open Source Tool bestimmen\n", + "## Open source tools for cross-grid-level electricity grid optimization developed in the open_eGo project - Learn-a-thon\n", "\n", "****\n", "\n", @@ -38,7 +38,8 @@ "\n", "* __[open_eGo Project Webpage](https://openegoproject.wordpress.com/)__\n", "* __[eTraGo Tool Documentation](http://etrago.readthedocs.io/en/latest/index.html)__ \n", - "* __[oedb Tutorials](http://oep.iks.cs.ovgu.de/dataedit/)__ How to use the OpenEnergy Database\n" + "* __[oedb Tutorials](http://oep.iks.cs.ovgu.de/dataedit/)__ How to use the OpenEnergy Database\n", + "* __[OpenMod Forum](https://forum.openmod-initiative.org/t/learn-a-thon-using-tools-for-cross-grid-level-electricity-grid-optimization-developed-in-the-open-ego-project/856)__ " ] }, { @@ -71,49 +72,8 @@ "\n", "## Installation \n", "\n", + "Please, find more information on the [README.md](https://github.com/openego/eGo/tree/features/tutorial/ego/examples/tutorials#etrago). \n", "\n", - "The python tool eTraGo can be used in several forms like from a terminal as an execution program, by integrated development environments (IDE) like [Spyder](https://anaconda.org/anaconda/spyder), [Jupyter notebooks](http://jupyter.org/install) or many more.\n", - "\n", - "A description how you to install and work with eTraGo can be found [here](http://etrago.readthedocs.io/en/latest/getting_started.html).\n", - "\n", - "\n", - "\n", - "### Notebook installation\n", - "\n", - "Having Python 3 installed? As eTraGo is designed as a Python package it is mandatory to have Python 3 installed. For this Tutorial we recommend to use an [virtual environment](https://virtualenv.pypa.io/en/stable/installation/). \n", - "See this [tutorial](https://docs.python.org/3/tutorial/venv.html). \n", - "\n", - "If you already have a Python 3 environment you can follow this steps in your terminal:\n", - "\n", - "\n", - "```desktop\n", - "\n", - "$ virtualenv etrago_ws --clear -p python3.5\n", - "$ cd etrago_ws\n", - "$ source bin/activate\n", - "\n", - "$ pip3 install etrago\n", - "$ pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA\n", - "\n", - "$ python3 -m pip install --upgrade pip\n", - "$ python3 -m pip install jupyter\n", - "\n", - "```\n", - "\n", - "### Start you Notebook\n", - "\n", - "```desktop\n", - "$ jupyter notebook\n", - "```\n", - "\n", - "See for more information [how to run your jupyter notebook](https://jupyter.readthedocs.io/en/latest/running.html#running).\n", - "\n", - "\n", - "\n", - "

Warning:

\n", - "For using this Notebook you need an oedb access or a database dump of the input data.
\n", - "

Note:

\n", - "The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/)\n", "\n", "## Import eTraGo packages\n", "\n", @@ -123,9 +83,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", @@ -157,9 +115,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# enable jupyter interactiv plotting\n", @@ -720,9 +676,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "openModZuerich", "language": "python", - "name": "python3" + "name": "openmodzuerich" }, "language_info": { "codemirror_mode": { @@ -734,7 +690,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.3" + "version": "3.5.2" } }, "nbformat": 4, From 6786a09cf2eb971a1759cd8c002fd00f2aaccb4b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 4 Jun 2018 14:51:01 +0200 Subject: [PATCH 014/314] change of dokumentation --- .../tutorials/etrago_ws_eum-fachtagung.ipynb | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb b/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb index 18f659f0..7a42f264 100644 --- a/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb +++ b/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb @@ -27,7 +27,7 @@ "metadata": {}, "source": [ "\n", - "#
OpenMod 2018 Workshop Zürich
\n", + "#
OpenMod Workshop Zürich 2018
\n", "\n", "## Open source tools for cross-grid-level electricity grid optimization developed in the open_eGo project - Learn-a-thon\n", "\n", @@ -147,9 +147,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "args_k10 = {# Setup and Configuration:\n", @@ -158,7 +156,8 @@ " 'method': 'lopf', # lopf or pf\n", " 'pf_post_lopf': False, # state whether you want to perform a pf after a lopf simulation\n", " 'start_snapshot': 4393, # 2.07.\n", - " 'end_snapshot' : 4400 'scn_name': 'Status Quo', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", + " 'end_snapshot' : 4400,\n", + " 'scn_name': 'NEP 2035', # state which scenario you want to run: Status Quo, NEP 2035, eGo100\n", " 'solver': 'glpk', # glpk, cplex or gurobi\n", " # Export options:\n", " 'lpfile': False, # state if and where you want to save pyomo's lp file: False or /path/tofolder\n", @@ -186,9 +185,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", @@ -199,9 +196,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# plot generation distripution\n", @@ -211,9 +206,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# plot stacked sum of nominal power for each generator type and timestep\n", @@ -224,9 +217,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# make a line loading plot\n", @@ -239,9 +230,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# plot to show extendable storages, if expanded\n", @@ -251,9 +240,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# get storage sizes in MW\n", @@ -270,9 +257,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# get snapshot\n", From e55535d8249300b1ddfb901561730f2fdc7126dd Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 4 Jun 2018 15:27:02 +0200 Subject: [PATCH 015/314] change installation add anaconda --- ego/examples/tutorials/README.md | 35 +++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index 5b1720cb..a4a5b292 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -4,12 +4,12 @@ eGo Tutorials -## Installation +## Installation ### eDisGo -### eTraGo +### eTraGo The python tool eTraGo can be used in several forms like from a terminal as an execution program, by integrated development environments (IDE) like [Spyder](https://anaconda.org/anaconda/spyder), [Jupyter notebooks](http://jupyter.org/install) or many more. @@ -18,8 +18,31 @@ A description how you to install and work with eTraGo can be found [here](http:/ ### Notebook installation -Having Python 3 installed? As eGo is designed as a Python package it is mandatory to have Python 3 installed. For this Tutorial we recommend to use an [virtual environment](https://virtualenv.pypa.io/en/stable/installation/). -See this [tutorial](https://docs.python.org/3/tutorial/venv.html). +#### with Anaconda + +Download and install your Python 3.x version of Anaconda [here](https://www.anaconda.com/download/). The full Documentation can be found [on this page.](https://docs.anaconda.com/anaconda/install/) + +We use Anaconda with an own environment in order to reduze problems with Packages and different versions on our system. + + +```desktop + +$ conda create --no-default-packages -n openModZuerich_env python 3.6 +$ source activate openModZuerich_env + +``` + +/home/.../anaconda3/envs/openModZuerich_env + + + +Learn more about [Anacona environments](https://conda.io/docs/user-guide/tasks/manage-environments.html). + + +#### without Anaconda + +Having Python 3 installed? As eGo is designed as a Python package it is mandatory to have Python 3 installed. For this Tutorial we recommend to use an [virtual environment](https://virtualenv.pypa.io/en/stable/installation/). +See this [tutorial](https://docs.python.org/3/tutorial/venv.html). If you already have a Python 3 environment you can follow this steps in your terminal: @@ -55,6 +78,4 @@ The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](h ## Import eTraGo packages -We are importing the [main function](https://github.com/openego/eTraGo/blob/dev/etrago/appl.py) of eTraGo and its database and plotting functions. - - +We are importing the [main function](https://github.com/openego/eTraGo/blob/dev/etrago/appl.py) of eTraGo and its database and plotting functions. From 72cefedd2e46d33a5935afb3bda7bd2622a7f26e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 4 Jun 2018 15:27:55 +0200 Subject: [PATCH 016/314] add requirment file --- ego/examples/tutorials/requirements.txt | 102 ++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 ego/examples/tutorials/requirements.txt diff --git a/ego/examples/tutorials/requirements.txt b/ego/examples/tutorials/requirements.txt new file mode 100644 index 00000000..e61c98f2 --- /dev/null +++ b/ego/examples/tutorials/requirements.txt @@ -0,0 +1,102 @@ +# Packages of Tutorial +# openMod_Zuerich2018 +###################### + +appdirs==1.4.3 +asn1crypto==0.24.0 +backcall==0.1.0 +bleach==2.1.3 +certifi==2018.4.16 +cffi==1.11.5 +chardet==3.0.4 +click==6.7 +click-plugins==1.0.3 +cligj==0.4.0 +cryptography==2.2.2 +cycler==0.10.0 +decorator==4.3.0 +demandlib==0.1.4 +descartes==1.1.0 +ding0==0.1.4 +eDisGo==0.0.2 +-e git+git@github.com:openego/eGo.git@6786a09cf2eb971a1759cd8c002fd00f2aaccb4b#egg=eGo +-e git+git@github.com:openego/ego.io.git@df52f0fc422b944a5edd10a94830950995ceb6f9#egg=egoio +entrypoints==0.2.3 +ephem==3.7.6.0 +eTraGo==0.5.1 +Fiona==1.7.11.post2 +GeoAlchemy2==0.4.0 +geopandas==0.3.0 +geopy==1.11.0 +html5lib==1.0.1 +idna==2.6 +ipykernel==4.8.2 +ipython==6.4.0 +ipython-genutils==0.2.0 +ipywidgets==7.2.1 +jedi==0.12.0 +jeepney==0.3.1 +Jinja2==2.10 +jsonschema==2.6.0 +jupyter-client==5.2.3 +jupyter-core==4.4.0 +keyring==12.2.1 +keyrings.alt==3.1 +linecache2==1.0.0 +lunardate==0.1.5 +MarkupSafe==1.0 +matplotlib==1.5.3 +mistune==0.8.3 +munch==2.3.2 +nbconvert==5.3.1 +nbformat==4.4.0 +networkx==1.11 +nose==1.3.7 +notebook==5.5.0 +numpy==1.14.3 +-e git+git@github.com:openego/oedialect.git@77c60477dde2e719fd2dac30ad6b679047c28ee0#egg=oedialect +pandas==0.20.3 +pandocfilters==1.4.2 +parso==0.2.1 +pexpect==4.6.0 +pickleshare==0.7.4 +plotly==2.2.3 +ply==3.11 +prompt-toolkit==1.0.15 +psycopg2==2.7.4 +psycopg2-binary==2.7.4 +ptyprocess==0.5.2 +pyCalverter==1.6.1 +pycparser==2.18 +Pygments==2.2.0 +Pyomo==5.1.1 +pyparsing==2.2.0 +pyproj==1.9.5.1 +-e git+https://github.com/openego/PyPSA.git@7a216db9e42a264827d55e725196362c4c221971#egg=pypsa +python-dateutil==2.7.3 +pytz==2018.4 +PyUtilib==5.6.3 +pyzmq==17.0.0 +requests==2.18.4 +Rtree==0.8.3 +scikit-learn==0.19.0 +scipy==0.19.1 +seaborn==0.8.1 +SecretStorage==3.0.1 +Send2Trash==1.5.0 +Shapely==1.6.3 +simplegeneric==0.8.1 +six==1.11.0 +SQLAlchemy==1.2.0 +terminado==0.8.1 +testpath==0.3.1 +tornado==5.0.2 +traceback2==1.4.0 +traitlets==4.3.2 +unittest2==1.1.0 +urllib3==1.22 +wcwidth==0.1.7 +webencodings==0.5.1 +widgetsnbextension==3.2.1 +workalendar==2.4.0 + From 56e9d0fb9c47b88b4903f4f2e86ff732c27743bf Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 07:22:45 +0200 Subject: [PATCH 017/314] update docu --- ego/examples/tutorials/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index a4a5b292..0d33c11c 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -30,6 +30,11 @@ We use Anaconda with an own environment in order to reduze problems with Package $ conda create --no-default-packages -n openModZuerich_env python 3.6 $ source activate openModZuerich_env + +... +$ conda env create --file requirements.yml +$ source activate openMod_Zuerich2018 + ``` /home/.../anaconda3/envs/openModZuerich_env From 9157b393e399193d5070be8d0e1e7d33f49dcbb5 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 07:24:15 +0200 Subject: [PATCH 018/314] add first yml trial --- ego/examples/tutorials/requirements.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 ego/examples/tutorials/requirements.yml diff --git a/ego/examples/tutorials/requirements.yml b/ego/examples/tutorials/requirements.yml new file mode 100644 index 00000000..12eb5aa4 --- /dev/null +++ b/ego/examples/tutorials/requirements.yml @@ -0,0 +1,23 @@ +name: openMod_Zuerich2018 + +channels: + - conda-forge + - anaconda + +dependencies: + - python=3.5 + - notebook # jupyter notebook + - numpy=1.14.3 + - pandas=0.20.3 + - pyyaml=3.12 + - requests + - sqlalchemy + - Rtree=0.8.3 + - scikit-learn + - scipy + - pip: + - ding0=0.1.4 + - eDisGo=0.0.2 + - "--editable=git+https://github.com/openego/eGo@dev#egg=eGo --process-dependency-links" + - "--editable=git+git@github.com:openego/oedialect.git@dev#egg=oedialect" + - "--editable=git+git@github.com:openego/ego.io.git@dev#egg=egoio" From 5f8117d426b1682b2950a665347ccf75464e6dec Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 09:41:23 +0200 Subject: [PATCH 019/314] update requirem and Docu --- ego/examples/tutorials/README.md | 54 +++++++++++++++++++------ ego/examples/tutorials/requirements.yml | 14 ++++--- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index 0d33c11c..c6d11944 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -1,22 +1,28 @@ -eGo Tutorials -------------- +# eGo Tutorials +## eDisGo +The python package eDisGo provides a toolbox for analysis and optimization of distribution grids. This software lives in the context of the research project open_eGo. It is closely related to the python project Ding0 as this project is currently the single data source for eDisGo providing synthetic grid data for whole Germany. -## Installation +Learn more about: +* [eDisGo – Optimization of flexibility options and grid expansion for distribution grids based on PyPSA](http://edisgo.readthedocs.io/en/dev/start_page.html) -### eDisGo +## eTraGo +Optimization of flexibility options for transmission grids based on PyPSA. + +A speciality in this context is that transmission grids are described by the 380, 220 and 110 kV in Germany. Conventionally the 110kV grid is part of the distribution grid. The integration of the transmission and ‘upper’ distribution grid is part of eTraGo. + +The focus of optimization are flexibility options with a special focus on energy storages and grid expansion measures. -### eTraGo The python tool eTraGo can be used in several forms like from a terminal as an execution program, by integrated development environments (IDE) like [Spyder](https://anaconda.org/anaconda/spyder), [Jupyter notebooks](http://jupyter.org/install) or many more. -A description how you to install and work with eTraGo can be found [here](http://etrago.readthedocs.io/en/latest/getting_started.html). +A general description how you to install and work with eTraGo can be found also [here](http://etrago.readthedocs.io/en/latest/getting_started.html). -### Notebook installation +# Notebook installation #### with Anaconda @@ -25,23 +31,45 @@ Download and install your Python 3.x version of Anaconda [here](https://www.anac We use Anaconda with an own environment in order to reduze problems with Packages and different versions on our system. -```desktop +##### Quick start - steps to do: + +1. Install Anacanda +2. Get eGo Repository from github +3. Create environment +4. Activate your environment -$ conda create --no-default-packages -n openModZuerich_env python 3.6 -$ source activate openModZuerich_env +5. Install you notebook requirements +6. Make few settings for your notebook (?) +7. Start your notebook and check if the notebook is running -... + +##### Get eGo Repository and install it with an environment +```desktop + +$ git clone git@github.com:openego/eGo.git +$ cd ../eGo/ego/examples/tutorials/ $ conda env create --file requirements.yml +``` + +##### Activate your environment and run your notebooks +```desktop + $ source activate openMod_Zuerich2018 +$ jupyter notebook +$ deactivate openMod_Zuerich2018 ``` -/home/.../anaconda3/envs/openModZuerich_env +##### fixes and work arounds: + +* setup kernel for your environment: +* ipython kernel install --user --name=openMod_Zuerich + -Learn more about [Anacona environments](https://conda.io/docs/user-guide/tasks/manage-environments.html). +Learn more about [Anacona environments](https://conda.io/docs/user-guide/tasks/manage-environments.html). Remove your environment with _'conda env remove -n openMod_Zuerich2018'_. #### without Anaconda diff --git a/ego/examples/tutorials/requirements.yml b/ego/examples/tutorials/requirements.yml index 12eb5aa4..b626f64f 100644 --- a/ego/examples/tutorials/requirements.yml +++ b/ego/examples/tutorials/requirements.yml @@ -15,9 +15,13 @@ dependencies: - Rtree=0.8.3 - scikit-learn - scipy + - ipywidgets - pip: - - ding0=0.1.4 - - eDisGo=0.0.2 - - "--editable=git+https://github.com/openego/eGo@dev#egg=eGo --process-dependency-links" - - "--editable=git+git@github.com:openego/oedialect.git@dev#egg=oedialect" - - "--editable=git+git@github.com:openego/ego.io.git@dev#egg=egoio" + - ding0==0.1.4 + - eDisGo==0.0.2 + - "--editable=git+git@github.com:openego/eGo@dev#egg=eGo --process-dependency-links" + - "--editable=git+git@github.com:openego/oedialect.git@master#egg=oedialect" + - "--editable=git+git@github.com:openego/ego.io.git@features/dialect#egg=egoio" + - "--editable=git+git@github.com:openego/PyPSA.git@dev#egg=pypsa" + - "--editable=git+git@github.com:openego/eTraGo.git@dev#egg=etrago" # eTraGo==0.5.1 + - "--editable=git+git@github.com:openego/tsam.git@master#egg=tsam" From 33c46a611f4e14527920f05e2f0ca429c2ef3da9 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 12:31:58 +0200 Subject: [PATCH 020/314] update files --- ego/examples/tutorials/README.md | 36 +++---- .../tutorials/etrago_ws_eum-fachtagung.ipynb | 78 +++++++++----- ego/examples/tutorials/requirements.txt | 102 ------------------ ego/examples/tutorials/requirements.yml | 2 +- 4 files changed, 63 insertions(+), 155 deletions(-) delete mode 100644 ego/examples/tutorials/requirements.txt diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index c6d11944..1d62bebf 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -28,7 +28,9 @@ A general description how you to install and work with eTraGo can be found also Download and install your Python 3.x version of Anaconda [here](https://www.anaconda.com/download/). The full Documentation can be found [on this page.](https://docs.anaconda.com/anaconda/install/) -We use Anaconda with an own environment in order to reduze problems with Packages and different versions on our system. +We use Anaconda with an own environment in order to reduze problems with Packages and different versions on our system. Learn more about [Anacona environments](https://conda.io/docs/user-guide/tasks/manage-environments.html). Remove your environment with _'conda env remove -n openMod_Zuerich2018'_. + + ##### Quick start - steps to do: @@ -37,7 +39,6 @@ We use Anaconda with an own environment in order to reduze problems with Package 2. Get eGo Repository from github 3. Create environment 4. Activate your environment - 5. Install you notebook requirements 6. Make few settings for your notebook (?) 7. Start your notebook and check if the notebook is running @@ -68,31 +69,22 @@ $ deactivate openMod_Zuerich2018 +##### API and ego.io settings -Learn more about [Anacona environments](https://conda.io/docs/user-guide/tasks/manage-environments.html). Remove your environment with _'conda env remove -n openMod_Zuerich2018'_. - - -#### without Anaconda - -Having Python 3 installed? As eGo is designed as a Python package it is mandatory to have Python 3 installed. For this Tutorial we recommend to use an [virtual environment](https://virtualenv.pypa.io/en/stable/installation/). -See this [tutorial](https://docs.python.org/3/tutorial/venv.html). - -If you already have a Python 3 environment you can follow this steps in your terminal: +* '.egoio', 'config.ini' ```desktop +[oedb] +username = +database = oedb +host = oe2.iws.cs.ovgu.de +port = 8080 +password = +``` -$ virtualenv ego_tutorial --clear -p python3.5 -$ cd ego_tutorial -$ source bin/activate - -$ pip3 install etrago==0.5.1 -$ pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA -$ python3 -m pip install --upgrade pip -$ python3 -m pip install jupyter -``` ### Start you Notebook @@ -108,7 +100,3 @@ See for more information [how to run your jupyter notebook](https://jupyter.read For using this Notebook you need an oedb access or a database dump of the input data.

Note:

The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/) - -## Import eTraGo packages - -We are importing the [main function](https://github.com/openego/eTraGo/blob/dev/etrago/appl.py) of eTraGo and its database and plotting functions. diff --git a/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb b/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb index 7a42f264..28ce2272 100644 --- a/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb +++ b/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb @@ -83,7 +83,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "import numpy as np\n", @@ -115,7 +117,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# enable jupyter interactiv plotting\n", @@ -147,7 +151,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "args_k10 = {# Setup and Configuration:\n", @@ -185,7 +191,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", @@ -196,7 +204,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# plot generation distripution\n", @@ -206,18 +216,24 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# plot stacked sum of nominal power for each generator type and timestep\n", "#fig.set_size_inches(14,14)\n", + "# fix error in .../eGo/ego/examples/tutorials/src/etrago/etrago/tools/plot.py\n", + "# 'wind_offshore':'skyblue', wind_onshore':'skyblue',\n", "plot_stacked_gen(network, resolution=\"MW\")" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# make a line loading plot\n", @@ -230,7 +246,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# plot to show extendable storages, if expanded\n", @@ -240,7 +258,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# get storage sizes in MW\n", @@ -257,7 +277,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# get snapshot\n", @@ -337,7 +359,7 @@ "source": [ "args_sh = {# Setup and Configuration:\n", " 'db': 'oedb', # db session\n", - " 'gridversion': None, # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", + " 'gridversion': \"v0.2.11\", # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", " 'method': 'lopf', # lopf or pf\n", " 'pf_post_lopf': False, # state whether you want to perform a pf after a lopf simulation\n", " 'start_snapshot': 4393, # 6552\n", @@ -371,7 +393,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -384,7 +406,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -396,7 +418,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -408,7 +430,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -423,7 +445,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -435,12 +457,12 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ "# curtailment per carrier / energy source\n", - "curtailment(network, carrier='wind')" + "curtailment(network, carrier='wind_onshore')" ] }, { @@ -479,7 +501,7 @@ "source": [ "args_lopf_pf = {# Setup and Configuration:\n", " 'db': 'oedb', # db session\n", - " 'gridversion': None, # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", + " 'gridversion': \"v0.2.11\", # None for model_draft or Version number (e.g. v0.2.11) for grid schema\n", " 'method': 'lopf', # lopf or pf\n", " 'pf_post_lopf': True, # state whether you want to perform a pf after a lopf simulation\n", " 'start_snapshot': 4393, \n", @@ -513,7 +535,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -526,7 +548,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -539,7 +561,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -564,7 +586,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -584,7 +606,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -629,7 +651,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -661,9 +683,9 @@ ], "metadata": { "kernelspec": { - "display_name": "openModZuerich", + "display_name": "openMod_Zuerich2018", "language": "python", - "name": "openmodzuerich" + "name": "openmod_zuerich2018" }, "language_info": { "codemirror_mode": { @@ -675,7 +697,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.2" + "version": "3.5.5" } }, "nbformat": 4, diff --git a/ego/examples/tutorials/requirements.txt b/ego/examples/tutorials/requirements.txt deleted file mode 100644 index e61c98f2..00000000 --- a/ego/examples/tutorials/requirements.txt +++ /dev/null @@ -1,102 +0,0 @@ -# Packages of Tutorial -# openMod_Zuerich2018 -###################### - -appdirs==1.4.3 -asn1crypto==0.24.0 -backcall==0.1.0 -bleach==2.1.3 -certifi==2018.4.16 -cffi==1.11.5 -chardet==3.0.4 -click==6.7 -click-plugins==1.0.3 -cligj==0.4.0 -cryptography==2.2.2 -cycler==0.10.0 -decorator==4.3.0 -demandlib==0.1.4 -descartes==1.1.0 -ding0==0.1.4 -eDisGo==0.0.2 --e git+git@github.com:openego/eGo.git@6786a09cf2eb971a1759cd8c002fd00f2aaccb4b#egg=eGo --e git+git@github.com:openego/ego.io.git@df52f0fc422b944a5edd10a94830950995ceb6f9#egg=egoio -entrypoints==0.2.3 -ephem==3.7.6.0 -eTraGo==0.5.1 -Fiona==1.7.11.post2 -GeoAlchemy2==0.4.0 -geopandas==0.3.0 -geopy==1.11.0 -html5lib==1.0.1 -idna==2.6 -ipykernel==4.8.2 -ipython==6.4.0 -ipython-genutils==0.2.0 -ipywidgets==7.2.1 -jedi==0.12.0 -jeepney==0.3.1 -Jinja2==2.10 -jsonschema==2.6.0 -jupyter-client==5.2.3 -jupyter-core==4.4.0 -keyring==12.2.1 -keyrings.alt==3.1 -linecache2==1.0.0 -lunardate==0.1.5 -MarkupSafe==1.0 -matplotlib==1.5.3 -mistune==0.8.3 -munch==2.3.2 -nbconvert==5.3.1 -nbformat==4.4.0 -networkx==1.11 -nose==1.3.7 -notebook==5.5.0 -numpy==1.14.3 --e git+git@github.com:openego/oedialect.git@77c60477dde2e719fd2dac30ad6b679047c28ee0#egg=oedialect -pandas==0.20.3 -pandocfilters==1.4.2 -parso==0.2.1 -pexpect==4.6.0 -pickleshare==0.7.4 -plotly==2.2.3 -ply==3.11 -prompt-toolkit==1.0.15 -psycopg2==2.7.4 -psycopg2-binary==2.7.4 -ptyprocess==0.5.2 -pyCalverter==1.6.1 -pycparser==2.18 -Pygments==2.2.0 -Pyomo==5.1.1 -pyparsing==2.2.0 -pyproj==1.9.5.1 --e git+https://github.com/openego/PyPSA.git@7a216db9e42a264827d55e725196362c4c221971#egg=pypsa -python-dateutil==2.7.3 -pytz==2018.4 -PyUtilib==5.6.3 -pyzmq==17.0.0 -requests==2.18.4 -Rtree==0.8.3 -scikit-learn==0.19.0 -scipy==0.19.1 -seaborn==0.8.1 -SecretStorage==3.0.1 -Send2Trash==1.5.0 -Shapely==1.6.3 -simplegeneric==0.8.1 -six==1.11.0 -SQLAlchemy==1.2.0 -terminado==0.8.1 -testpath==0.3.1 -tornado==5.0.2 -traceback2==1.4.0 -traitlets==4.3.2 -unittest2==1.1.0 -urllib3==1.22 -wcwidth==0.1.7 -webencodings==0.5.1 -widgetsnbextension==3.2.1 -workalendar==2.4.0 - diff --git a/ego/examples/tutorials/requirements.yml b/ego/examples/tutorials/requirements.yml index b626f64f..b53130b0 100644 --- a/ego/examples/tutorials/requirements.yml +++ b/ego/examples/tutorials/requirements.yml @@ -23,5 +23,5 @@ dependencies: - "--editable=git+git@github.com:openego/oedialect.git@master#egg=oedialect" - "--editable=git+git@github.com:openego/ego.io.git@features/dialect#egg=egoio" - "--editable=git+git@github.com:openego/PyPSA.git@dev#egg=pypsa" - - "--editable=git+git@github.com:openego/eTraGo.git@dev#egg=etrago" # eTraGo==0.5.1 + - "--editable=git+git@github.com:openego/eTraGo.git@0.5.1#egg=etrago" # eTraGo==0.5.1 - "--editable=git+git@github.com:openego/tsam.git@master#egg=tsam" From 518fe2c4e8147fa3632907620e93fe48a686497c Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 13:21:25 +0200 Subject: [PATCH 021/314] change io confic --- ego/examples/tutorials/README.md | 13 +++++-------- ...htagung.ipynb => etrago_OpenMod_Zuerich18.ipynb} | 0 2 files changed, 5 insertions(+), 8 deletions(-) rename ego/examples/tutorials/{etrago_ws_eum-fachtagung.ipynb => etrago_OpenMod_Zuerich18.ipynb} (100%) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index 1d62bebf..5a2e5504 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -76,12 +76,12 @@ $ deactivate openMod_Zuerich2018 ```desktop [oedb] -username = +dialect = oedialect +username = database = oedb -host = oe2.iws.cs.ovgu.de -port = 8080 -password = -``` +host = openenergy-platform.org +port = +password = ``` @@ -95,8 +95,5 @@ $ jupyter notebook See for more information [how to run your jupyter notebook](https://jupyter.readthedocs.io/en/latest/running.html#running). - -

Warning:

-For using this Notebook you need an oedb access or a database dump of the input data.

Note:

The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/) diff --git a/ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb b/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb similarity index 100% rename from ego/examples/tutorials/etrago_ws_eum-fachtagung.ipynb rename to ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb From 5c9a5ba2be68c0632a01d4a866f4d6f0a5456299 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 14:25:41 +0200 Subject: [PATCH 022/314] change readme --- ego/examples/tutorials/README.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index 5a2e5504..75ee03e8 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -40,7 +40,7 @@ We use Anaconda with an own environment in order to reduze problems with Package 3. Create environment 4. Activate your environment 5. Install you notebook requirements -6. Make few settings for your notebook (?) +6. Make few settings for your notebook 7. Start your notebook and check if the notebook is running @@ -48,8 +48,8 @@ We use Anaconda with an own environment in order to reduze problems with Package ##### Get eGo Repository and install it with an environment ```desktop -$ git clone git@github.com:openego/eGo.git -$ cd ../eGo/ego/examples/tutorials/ +$ git clone -b features/tutorial https://git@github.com/openego/eGo.git +$ cd eGo/ego/examples/tutorials/ $ conda env create --file requirements.yml ``` @@ -58,20 +58,18 @@ $ conda env create --file requirements.yml $ source activate openMod_Zuerich2018 $ jupyter notebook -$ deactivate openMod_Zuerich2018 - +$ source deactivate ``` ##### fixes and work arounds: -* setup kernel for your environment: -* ipython kernel install --user --name=openMod_Zuerich - +* Error in function plot_stacked_gen() due to data name changes. Fix error in ../eGo/ego/examples/tutorials/src/etrago/etrago/tools/plot.py and add: 'wind_offshore':'skyblue', 'wind_onshore':'skyblue', instead of 'wind'; restart kernel +plot_stacked_gen(network, resolution="MW") ##### API and ego.io settings -* '.egoio', 'config.ini' +Your API settings will be saved in the folder .egoio in the file config.ini. ```desktop @@ -84,8 +82,6 @@ port = password = ``` - - ### Start you Notebook ```desktop @@ -96,4 +92,4 @@ See for more information [how to run your jupyter notebook](https://jupyter.read

Note:

-The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/) +The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/) From 365f3b0033354d774e8a4d9fd800c9d3124dc7f0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 14:29:28 +0200 Subject: [PATCH 023/314] add import oedialect --- .../tutorials/etrago_OpenMod_Zuerich18.ipynb | 87 +++++-------------- 1 file changed, 24 insertions(+), 63 deletions(-) diff --git a/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb b/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb index 28ce2272..243bd1f2 100644 --- a/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb +++ b/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb @@ -83,9 +83,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", @@ -93,6 +91,7 @@ "from numpy import genfromtxt\n", "np.random.seed()\n", "import time\n", + "import oedialect\n", "\n", "import os\n", "\n", @@ -191,9 +190,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", @@ -204,9 +201,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plot generation distripution\n", @@ -216,9 +211,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plot stacked sum of nominal power for each generator type and timestep\n", @@ -231,9 +224,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# make a line loading plot\n", @@ -246,9 +237,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plot to show extendable storages, if expanded\n", @@ -258,9 +247,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# get storage sizes in MW\n", @@ -277,9 +264,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# get snapshot\n", @@ -392,9 +377,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", @@ -405,9 +388,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plot generation distripution\n", @@ -417,9 +398,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plot stacked sum of nominal power for each generator type and timestep\n", @@ -429,9 +408,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plots\n", @@ -444,9 +421,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plot to show extendable storages\n", @@ -456,9 +431,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# curtailment per carrier / energy source\n", @@ -534,9 +507,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", @@ -547,9 +518,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plot stacked sum of nominal power for each generator type and timestep\n", @@ -560,9 +529,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# plots\n", @@ -585,9 +552,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "\n", @@ -605,9 +570,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Line losses\n", @@ -650,9 +613,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# get snapshot\n", @@ -683,9 +644,9 @@ ], "metadata": { "kernelspec": { - "display_name": "openMod_Zuerich2018", + "display_name": "Python 3", "language": "python", - "name": "openmod_zuerich2018" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -697,7 +658,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.5" + "version": "3.6.3" } }, "nbformat": 4, From abfade7d52c0aa456a47afb3677871a22a665571 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 15:45:56 +0200 Subject: [PATCH 024/314] update requirem. --- ego/examples/tutorials/README.md | 1 + ego/examples/tutorials/requirements.yml | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index 75ee03e8..ddbdd0fc 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -92,4 +92,5 @@ See for more information [how to run your jupyter notebook](https://jupyter.read

Note:

+ The installation is only tested on Ubuntu 16.4. and Windows 10 with [Anaconda](https://www.anaconda.com/download/) diff --git a/ego/examples/tutorials/requirements.yml b/ego/examples/tutorials/requirements.yml index b53130b0..c273f8c3 100644 --- a/ego/examples/tutorials/requirements.yml +++ b/ego/examples/tutorials/requirements.yml @@ -18,10 +18,11 @@ dependencies: - ipywidgets - pip: - ding0==0.1.4 - - eDisGo==0.0.2 - - "--editable=git+git@github.com:openego/eGo@dev#egg=eGo --process-dependency-links" + - "--editable=git+git@github.com:openego/eGo.git@dev#egg=eGo --process-dependency-links" - "--editable=git+git@github.com:openego/oedialect.git@master#egg=oedialect" - "--editable=git+git@github.com:openego/ego.io.git@features/dialect#egg=egoio" - "--editable=git+git@github.com:openego/PyPSA.git@dev#egg=pypsa" - "--editable=git+git@github.com:openego/eTraGo.git@0.5.1#egg=etrago" # eTraGo==0.5.1 - "--editable=git+git@github.com:openego/tsam.git@master#egg=tsam" + - "--editable=git+git@github.com:openego/eDisGo.git@dev#egg=edisgo" + From 7ce1a91dc55e9e36e6433cf5eea4653c2e4a4363 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 16:06:11 +0200 Subject: [PATCH 025/314] update notebook --- .../tutorials/etrago_OpenMod_Zuerich18.ipynb | 82 ++++++++++++++----- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb b/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb index 243bd1f2..0c7f115f 100644 --- a/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb +++ b/ego/examples/tutorials/etrago_OpenMod_Zuerich18.ipynb @@ -83,7 +83,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "import numpy as np\n", @@ -190,7 +192,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", @@ -201,7 +205,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# plot generation distripution\n", @@ -211,7 +217,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# plot stacked sum of nominal power for each generator type and timestep\n", @@ -224,7 +232,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# make a line loading plot\n", @@ -237,7 +247,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# plot to show extendable storages, if expanded\n", @@ -247,7 +259,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# get storage sizes in MW\n", @@ -264,7 +278,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# get snapshot\n", @@ -377,7 +393,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", @@ -388,7 +406,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# plot generation distripution\n", @@ -398,7 +418,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# plot stacked sum of nominal power for each generator type and timestep\n", @@ -408,7 +430,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# plots\n", @@ -421,7 +445,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# plot to show extendable storages\n", @@ -431,7 +457,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# curtailment per carrier / energy source\n", @@ -507,7 +535,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# Start eTraGo calculation with args setting\n", @@ -518,7 +548,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# plot stacked sum of nominal power for each generator type and timestep\n", @@ -529,7 +561,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# plots\n", @@ -552,7 +586,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "\n", @@ -570,7 +606,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# Line losses\n", @@ -613,7 +651,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# get snapshot\n", @@ -658,7 +698,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.3" + "version": "3.5.5" } }, "nbformat": 4, From f93a1c62982c171b76f4a342ccf1bdca2a2cb00b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 16:08:57 +0200 Subject: [PATCH 026/314] update file --- ego/examples/tutorials/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index ddbdd0fc..40c690a1 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -35,6 +35,7 @@ We use Anaconda with an own environment in order to reduze problems with Package ##### Quick start - steps to do: +0. Sign-in on [openenergy-platform.org](http://openenergy-platform.org/login/) 1. Install Anacanda 2. Get eGo Repository from github 3. Create environment From eb8ccec94a3c63504fab0ad91f1fb9c55f641c52 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 5 Jun 2018 19:52:13 +0200 Subject: [PATCH 027/314] update file --- ego/examples/tutorials/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index 40c690a1..9123b00e 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -80,7 +80,8 @@ username = database = oedb host = openenergy-platform.org port = -password = ``` +password = +``` ### Start you Notebook From 1a3b357a5c8783a14522797afee936286f75c288 Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Tue, 5 Jun 2018 22:53:42 +0200 Subject: [PATCH 028/314] add port --- ego/examples/tutorials/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/examples/tutorials/README.md b/ego/examples/tutorials/README.md index 9123b00e..2d30992a 100644 --- a/ego/examples/tutorials/README.md +++ b/ego/examples/tutorials/README.md @@ -79,7 +79,7 @@ dialect = oedialect username = database = oedb host = openenergy-platform.org -port = +port = 80 password = ``` From 07956b0ff66e87bf185fe6e7b1574d6dd9eb8b99 Mon Sep 17 00:00:00 2001 From: Birgit Schachler Date: Wed, 6 Jun 2018 12:31:51 +0200 Subject: [PATCH 029/314] Add edisgo tutorial --- .../tutorials/edisgo_simple_example.ipynb | 1495 +++++++++++++++++ ego/examples/tutorials/grid_1476.png | Bin 0 -> 410425 bytes 2 files changed, 1495 insertions(+) create mode 100644 ego/examples/tutorials/edisgo_simple_example.ipynb create mode 100644 ego/examples/tutorials/grid_1476.png diff --git a/ego/examples/tutorials/edisgo_simple_example.ipynb b/ego/examples/tutorials/edisgo_simple_example.ipynb new file mode 100644 index 00000000..0581729a --- /dev/null +++ b/ego/examples/tutorials/edisgo_simple_example.ipynb @@ -0,0 +1,1495 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "__copyright__ = \"Reiner Lemoine Institut gGmbH\"\n", + "__license__ = \"GNU Affero General Public License Version 3 (AGPL-3.0)\"\n", + "__url__ = \"https://github.com/openego/eDisGo/blob/master/LICENSE\"\n", + "__author__ = \"gplssm, birgits\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Welcome to the eDisGo example\n", + "\n", + "eDisGo is a **python toolbox for the analysis of distribution networks** (low and medium voltage) that can be used to investigate economically viable **network expansion** scenarios, considering alternative flexibility options such as **storages or redispatch**. \n", + "\n", + "eDisGo is developed in the [open_eGo research project](https://openegoproject.wordpress.com/). It is based on [PyPSA](https://pypsa.org/), a toolbox for simulation and optimization of power networks, and closely related to the [ding0](https://dingo.readthedocs.io/en/dev/) project. ding0 stands for distribution network generator and is a tool to generate synthetic status quo medium and low voltage power distribution networks based on open (or at least accessible) data. It is currently the single data source for eDisGo providing synthetic grid data for whole Germany.\n", + "\n", + "**! eDisGo is work in progress !** Please be aware that some of its features may still be buggy and not yet very sophisticated. We are happy for any bug reports, hints, etc. you may have for us.\n", + "\n", + "### Learn more about eDisGo\n", + "\n", + "* __[eDisGo Source Code](https://github.com/openego/eDisGo)__\n", + "* __[eDisGo Documentation](http://edisgo.readthedocs.io/en/dev/)__\n", + "\n", + "### Table of Contents\n", + "\n", + "* [The eDisGo API](#settings)\n", + "* [The eDisGo data container and grid data structure](#network)\n", + "* [Future generator capacities](#generator_scenario)\n", + "* [Grid reinforcement](#grid_reinforcement)\n", + "* [Evaluate results](#evaluation)\n", + "* [References](#references)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## About the example\n", + "\n", + "This example shows the general usage of eDisGo. Grid expansion costs for an example distribution grid (see image below) are calculated assuming additional renewable energy generators as stated in the open_eGo 'NEP 2035' scenario (based on the scenario framework of the German grid development plan (Netzentwicklungsplan) for the year 2035) and conducting a worst-case analysis. Moreover, the eDisGo network data structure and how to access the results are introduced. At the end of the example grid expansion costs for a different scenario are calculated and compared to the grid expansion costs in the 'NEP 2035' scenario.\n", + "\n", + "\n", + "\n", + "**Let's get started!** First of all we have to import some packages." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Import packages" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/Birgit.Schachler/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use \"pip install psycopg2-binary\" instead. For details see: .\n", + " \"\"\")\n", + "INFO:keyring.backend:Loading SecretService\n", + "INFO:keyring.backend:Loading kwallet\n", + "INFO:keyring.backend:Loading macOS\n", + "INFO:keyring.backend:Loading windows\n", + "INFO:keyring.backend:Loading Gnome\n", + "INFO:keyring.backend:Loading Google\n", + "INFO:keyring.backend:Loading Windows (alt)\n", + "INFO:keyring.backend:Loading file\n", + "INFO:keyring.backend:Loading keyczar\n", + "INFO:keyring.backend:Loading multi\n", + "INFO:keyring.backend:Loading pyfs\n" + ] + } + ], + "source": [ + "import os\n", + "import sys\n", + "import pandas as pd\n", + "\n", + "from edisgo import EDisGo\n", + "\n", + "import logging\n", + "logging.basicConfig(level=logging.ERROR)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The eDisGo API \n", + "\n", + "The top-level API for setting up your scenario, invoking grid expansion and flexibility measures, etc. is provided by the **EDisGo class** (see [class documentation](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.network.EDisGo) for more information).\n", + "\n", + "In this example we simply want to do a worst-case analysis of a ding0 grid. For this, we only have to provide a grid and set the 'worst_case_analysis' parameter. \n", + "\n", + "#### Specifying the ding0 grid\n", + "\n", + "The ding0 grid is specified through the input parameter 'ding0_grid'. The following assumes you have a file of a ding0 grid named “ding0_grids__6.pkl” in current working directory.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "ding0_grid = os.path.join(sys.path[0], \"ding0_grids_239_DPv0.4.0.pkl\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Specifying worst-case analysis\n", + "\n", + "As worst-case analysis you can either just analyse the feed-in or the load case or do a combined analysis. Choose between the following options:\n", + "\n", + "* **’worst-case-feedin’** \n", + " \n", + " Feed-in and demand for the worst-case scenario \"feed-in case\" are generated. Demand is set to 15% of maximum demand for loads connected to the MV grid and 10% for loads connected to the LV grid. Feed-in of all generators is set to nominal power of the generator, except for PV systems where it is set to 85% of the nominal power.\n", + "\n", + " \n", + "* **’worst-case-load’**\n", + "\n", + " Feed-in and demand for the worst-case scenario \"load case\" are generated. Demand of all loads is set to maximum demand. Feed-in of all generators is set to zero.\n", + "\n", + "\n", + "* **’worst-case’**\n", + " \n", + " Feed-in and demand for the two worst-case scenarios \"feed-in case\" and \"load case\" are generated.\n", + "\n", + "Instead of doing a worst-case analysis you can also provide your own timeseries for demand and feed-in and use those in the network analysis. EDisGo also offers methods to generate load and feed-in time series. Check out the [EDisGo class documentation](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.network.EDisGo) for more information." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "worst_case_analysis = 'worst-case-feedin'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we are ready to initialize the edisgo API object." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "edisgo = EDisGo(ding0_grid=ding0_grid,\n", + " worst_case_analysis=worst_case_analysis)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The eDisGo data container and grid data structure \n", + "\n", + "The last line, besides a couple of other things, initialized the [Network class](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.network.Network) which serves as an overall data container in eDisGo holding the grid data for the [MV grid](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.grids.MVGrid) and [LV grids](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.grids.LVGrid), [config data](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.network.Config), [results](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.network.Results), [timeseries](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.network.TimeSeries), etc. It is linked from multiple locations and provides hierarchical access to all data. Network itself can be accessed via the EDisGo API object as follows:\n", + "\n", + "```python\n", + "edisgo.network\n", + "```\n", + "\n", + "As mentioned *Network* holds the MV grid and LV grids. The grid topology is represented by separate undirected graphs for the MV grid and each of the LV grids. Each of these graphs is an eDisGo [Graph](http://edisgo.readthedocs.io/en/dev/_modules/edisgo/grid/grids.html#Graph), which is subclassed from networkx.Graph and extended by extra-functionality. Lines represent edges in the graph. Other equipment is represented by a node. Let's have a look into the graph.\n", + "\n", + "First we take a look at all the **lines**." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{GeneratorFluctuating_839361: {GeneratorFluctuating_878867: {'type': 'line',\n", + " 'line': Line_2390003},\n", + " BranchTee_MVGrid_239_86: {'type': 'line', 'line': Line_2390004}},\n", + " GeneratorFluctuating_839362: {BranchTee_MVGrid_239_87: {'type': 'line',\n", + " 'line': Line_2390005}},\n", + " GeneratorFluctuating_839363: {BranchTee_MVGrid_239_88: {'type': 'line',\n", + " 'line': Line_2390006}},\n", + " GeneratorFluctuating_839364: {LVStation_119612: {'type': 'line',\n", + " 'line': Line_2390007}},\n", + " GeneratorFluctuating_878450: {BranchTee_MVGrid_239_89: {'type': 'line',\n", + " 'line': Line_2390008}},\n", + " GeneratorFluctuating_878583: {BranchTee_MVGrid_239_84: {'type': 'line',\n", + " 'line': Line_2390001}},\n", + " GeneratorFluctuating_878609: {MVStation_239: {'type': 'line',\n", + " 'line': Line_2390009}},\n", + " GeneratorFluctuating_878611: {MVStation_239: {'type': 'line',\n", + " 'line': Line_2390010}},\n", + " GeneratorFluctuating_878614: {MVStation_239: {'type': 'line',\n", + " 'line': Line_2390011}},\n", + " GeneratorFluctuating_878615: {MVStation_239: {'type': 'line',\n", + " 'line': Line_2390012}},\n", + " GeneratorFluctuating_878862: {BranchTee_MVGrid_239_90: {'type': 'line',\n", + " 'line': Line_2390013}},\n", + " GeneratorFluctuating_878863: {BranchTee_MVGrid_239_91: {'type': 'line',\n", + " 'line': Line_2390014}},\n", + " GeneratorFluctuating_878864: {BranchTee_MVGrid_239_92: {'type': 'line',\n", + " 'line': Line_2390015}},\n", + " GeneratorFluctuating_878865: {BranchTee_MVGrid_239_93: {'type': 'line',\n", + " 'line': Line_2390016}},\n", + " GeneratorFluctuating_878866: {BranchTee_MVGrid_239_94: {'type': 'line',\n", + " 'line': Line_2390017}},\n", + " GeneratorFluctuating_878867: {GeneratorFluctuating_839361: {'type': 'line',\n", + " 'line': Line_2390003}},\n", + " GeneratorFluctuating_878875: {MVStation_239: {'type': 'line',\n", + " 'line': Line_2390018}},\n", + " GeneratorFluctuating_878950: {MVStation_239: {'type': 'line',\n", + " 'line': Line_2390019}},\n", + " GeneratorFluctuating_878963: {BranchTee_MVGrid_239_85: {'type': 'line',\n", + " 'line': Line_2390002}},\n", + " BranchTee_MVGrid_239_1: {LVStation_119897: {'type': 'line',\n", + " 'line': Line_2390050},\n", + " MVDisconnectingPoint_1: {'line': Line_2390252, 'type': 'line'}},\n", + " BranchTee_MVGrid_239_2: {MVStation_239: {'type': 'line',\n", + " 'line': Line_2390266},\n", + " MVDisconnectingPoint_2: {'line': Line_2390265, 'type': 'line'}},\n", + " BranchTee_MVGrid_239_3: {LVStation_125269: {'type': 'line',\n", + " 'line': Line_2390181},\n", + " BranchTee_MVGrid_239_88: {'type': 'line', 'line': Line_2390273},\n", + " BranchTee_MVGrid_239_89: {'type': 'line', 'line': Line_2390274}},\n", + " BranchTee_MVGrid_239_4: {LVStation_119904: {'type': 'line',\n", + " 'line': Line_2390055},\n", + " BranchTee_MVGrid_239_18: {'type': 'line', 'line': Line_2390251},\n", + " BranchTee_MVGrid_239_20: {'type': 'line', 'line': Line_2390254}},\n", + " BranchTee_MVGrid_239_5: {LVStation_120736: {'type': 'line',\n", + " 'line': Line_2390071},\n", + " BranchTee_MVGrid_239_6: {'type': 'line', 'line': Line_2390277},\n", + " BranchTee_MVGrid_239_8: {'type': 'line', 'line': Line_2390278}},\n", + " BranchTee_MVGrid_239_6: {LVStation_120411: {'type': 'line',\n", + " 'line': Line_2390064},\n", + " BranchTee_MVGrid_239_25: {'type': 'line', 'line': Line_2390260},\n", + " BranchTee_MVGrid_239_5: {'type': 'line', 'line': Line_2390277}},\n", + " BranchTee_MVGrid_239_7: {LVStation_120470: {'type': 'line',\n", + " 'line': Line_2390065},\n", + " LVStation_419726: {'type': 'line', 'line': Line_2390224},\n", + " BranchTee_MVGrid_239_8: {'type': 'line', 'line': Line_2390285}},\n", + " BranchTee_MVGrid_239_8: {LVStation_419795: {'type': 'line',\n", + " 'line': Line_2390225},\n", + " BranchTee_MVGrid_239_5: {'type': 'line', 'line': Line_2390278},\n", + " BranchTee_MVGrid_239_7: {'type': 'line', 'line': Line_2390285}},\n", + " BranchTee_MVGrid_239_9: {LVStation_120555: {'type': 'line',\n", + " 'line': Line_2390067},\n", + " LVStation_120585: {'type': 'line', 'line': Line_2390069},\n", + " BranchTee_MVGrid_239_10: {'type': 'line', 'line': Line_2390242}},\n", + " BranchTee_MVGrid_239_10: {LVStation_511325: {'type': 'line',\n", + " 'line': Line_2390238},\n", + " BranchTee_MVGrid_239_13: {'type': 'line', 'line': Line_2390241},\n", + " BranchTee_MVGrid_239_9: {'type': 'line', 'line': Line_2390242}},\n", + " BranchTee_MVGrid_239_11: {LVStation_120898: {'type': 'line',\n", + " 'line': Line_2390076},\n", + " LVStation_418244: {'type': 'line', 'line': Line_2390219},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390243}},\n", + " BranchTee_MVGrid_239_12: {LVStation_120943: {'type': 'line',\n", + " 'line': Line_2390080},\n", + " LVStation_419885: {'type': 'line', 'line': Line_2390226},\n", + " BranchTee_MVGrid_239_84: {'type': 'line', 'line': Line_2390244}},\n", + " BranchTee_MVGrid_239_13: {LVStation_121317: {'type': 'line',\n", + " 'line': Line_2390087},\n", + " LVStation_416441: {'type': 'line', 'line': Line_2390204},\n", + " BranchTee_MVGrid_239_10: {'type': 'line', 'line': Line_2390241}},\n", + " BranchTee_MVGrid_239_14: {LVStation_121289: {'type': 'line',\n", + " 'line': Line_2390086},\n", + " LVStation_417530: {'type': 'line', 'line': Line_2390211},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390245}},\n", + " BranchTee_MVGrid_239_15: {LVStation_121776: {'type': 'line',\n", + " 'line': Line_2390096},\n", + " BranchTee_MVGrid_239_29: {'type': 'line', 'line': Line_2390246},\n", + " BranchTee_MVGrid_239_55: {'type': 'line', 'line': Line_2390247}},\n", + " BranchTee_MVGrid_239_16: {LVStation_417276: {'type': 'line',\n", + " 'line': Line_2390210},\n", + " BranchTee_MVGrid_239_19: {'type': 'line', 'line': Line_2390248},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390249}},\n", + " BranchTee_MVGrid_239_17: {LVStation_124110: {'type': 'line',\n", + " 'line': Line_2390148},\n", + " LVStation_416815: {'type': 'line', 'line': Line_2390207},\n", + " LVStation_416983: {'type': 'line', 'line': Line_2390209}},\n", + " BranchTee_MVGrid_239_18: {LVStation_121940: {'type': 'line',\n", + " 'line': Line_2390110},\n", + " BranchTee_MVGrid_239_29: {'type': 'line', 'line': Line_2390250},\n", + " BranchTee_MVGrid_239_4: {'type': 'line', 'line': Line_2390251}},\n", + " BranchTee_MVGrid_239_19: {LVStation_121919: {'type': 'line',\n", + " 'line': Line_2390108},\n", + " LVStation_416589: {'type': 'line', 'line': Line_2390206},\n", + " BranchTee_MVGrid_239_16: {'type': 'line', 'line': Line_2390248}},\n", + " BranchTee_MVGrid_239_20: {LVStation_419079: {'type': 'line',\n", + " 'line': Line_2390223},\n", + " BranchTee_MVGrid_239_35: {'type': 'line', 'line': Line_2390253},\n", + " BranchTee_MVGrid_239_4: {'type': 'line', 'line': Line_2390254}},\n", + " BranchTee_MVGrid_239_21: {LVStation_121879: {'type': 'line',\n", + " 'line': Line_2390099},\n", + " LVStation_122400: {'type': 'line', 'line': Line_2390128},\n", + " BranchTee_MVGrid_239_34: {'type': 'line', 'line': Line_2390255}},\n", + " BranchTee_MVGrid_239_22: {LVStation_122077: {'type': 'line',\n", + " 'line': Line_2390115},\n", + " LVStation_122078: {'type': 'line', 'line': Line_2390117},\n", + " LVStation_418237: {'type': 'line', 'line': Line_2390218}},\n", + " BranchTee_MVGrid_239_23: {LVStation_124085: {'type': 'line',\n", + " 'line': Line_2390144},\n", + " BranchTee_MVGrid_239_43: {'type': 'line', 'line': Line_2390256},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390257}},\n", + " BranchTee_MVGrid_239_24: {LVStation_416449: {'type': 'line',\n", + " 'line': Line_2390205},\n", + " BranchTee_MVGrid_239_70: {'type': 'line', 'line': Line_2390258},\n", + " BranchTee_MVGrid_239_85: {'type': 'line', 'line': Line_2390259}},\n", + " BranchTee_MVGrid_239_25: {LVStation_503036: {'type': 'line',\n", + " 'line': Line_2390237},\n", + " BranchTee_MVGrid_239_6: {'type': 'line', 'line': Line_2390260},\n", + " BranchTee_MVGrid_239_76: {'type': 'line', 'line': Line_2390261}},\n", + " BranchTee_MVGrid_239_26: {LVStation_417550: {'type': 'line',\n", + " 'line': Line_2390213},\n", + " LVStation_417936: {'type': 'line', 'line': Line_2390216},\n", + " BranchTee_MVGrid_239_64: {'type': 'line', 'line': Line_2390262}},\n", + " BranchTee_MVGrid_239_27: {LVStation_417909: {'type': 'line',\n", + " 'line': Line_2390215},\n", + " LVStation_417987: {'type': 'line', 'line': Line_2390217},\n", + " BranchTee_MVGrid_239_78: {'type': 'line', 'line': Line_2390263}},\n", + " BranchTee_MVGrid_239_28: {LVStation_122077: {'type': 'line',\n", + " 'line': Line_2390116},\n", + " LVStation_122426: {'type': 'line', 'line': Line_2390132},\n", + " BranchTee_MVGrid_239_54: {'type': 'line', 'line': Line_2390264}},\n", + " BranchTee_MVGrid_239_29: {LVStation_122480: {'type': 'line',\n", + " 'line': Line_2390133},\n", + " BranchTee_MVGrid_239_15: {'type': 'line', 'line': Line_2390246},\n", + " BranchTee_MVGrid_239_18: {'type': 'line', 'line': Line_2390250}},\n", + " BranchTee_MVGrid_239_30: {BranchTee_MVGrid_239_32: {'type': 'line',\n", + " 'line': Line_2390267},\n", + " BranchTee_MVGrid_239_35: {'type': 'line', 'line': Line_2390268},\n", + " BranchTee_MVGrid_239_91: {'type': 'line', 'line': Line_2390269}},\n", + " BranchTee_MVGrid_239_31: {LVStation_139149: {'type': 'line',\n", + " 'line': Line_2390189},\n", + " LVStation_139186: {'type': 'line', 'line': Line_2390198},\n", + " BranchTee_MVGrid_239_34: {'type': 'line', 'line': Line_2390270}},\n", + " BranchTee_MVGrid_239_32: {LVStation_139104: {'type': 'line',\n", + " 'line': Line_2390184},\n", + " BranchTee_MVGrid_239_30: {'type': 'line', 'line': Line_2390267},\n", + " BranchTee_MVGrid_239_33: {'type': 'line', 'line': Line_2390271}},\n", + " BranchTee_MVGrid_239_33: {LVStation_419885: {'type': 'line',\n", + " 'line': Line_2390227},\n", + " BranchTee_MVGrid_239_32: {'type': 'line', 'line': Line_2390271},\n", + " BranchTee_MVGrid_239_86: {'type': 'line', 'line': Line_2390272}},\n", + " BranchTee_MVGrid_239_34: {LVStation_139150: {'type': 'line',\n", + " 'line': Line_2390191},\n", + " BranchTee_MVGrid_239_21: {'type': 'line', 'line': Line_2390255},\n", + " BranchTee_MVGrid_239_31: {'type': 'line', 'line': Line_2390270}},\n", + " BranchTee_MVGrid_239_35: {LVStation_122231: {'type': 'line',\n", + " 'line': Line_2390127},\n", + " BranchTee_MVGrid_239_20: {'type': 'line', 'line': Line_2390253},\n", + " BranchTee_MVGrid_239_30: {'type': 'line', 'line': Line_2390268}},\n", + " BranchTee_MVGrid_239_36: {LVStation_118322: {'type': 'line',\n", + " 'line': Line_2390020},\n", + " LVStation_118323: {'type': 'line', 'line': Line_2390021},\n", + " LVStation_124111: {'type': 'line', 'line': Line_2390150}},\n", + " BranchTee_MVGrid_239_37: {LVStation_118324: {'type': 'line',\n", + " 'line': Line_2390023},\n", + " LVStation_515314: {'type': 'line', 'line': Line_2390240}},\n", + " BranchTee_MVGrid_239_38: {LVStation_119612: {'type': 'line',\n", + " 'line': Line_2390024},\n", + " LVStation_119613: {'type': 'line', 'line': Line_2390026},\n", + " LVStation_417898: {'type': 'line', 'line': Line_2390214}},\n", + " BranchTee_MVGrid_239_39: {LVStation_119698: {'type': 'line',\n", + " 'line': Line_2390029}},\n", + " BranchTee_MVGrid_239_40: {LVStation_119701: {'type': 'line',\n", + " 'line': Line_2390032},\n", + " LVStation_119704: {'type': 'line', 'line': Line_2390035}},\n", + " BranchTee_MVGrid_239_41: {LVStation_119891: {'type': 'line',\n", + " 'line': Line_2390040},\n", + " LVStation_119894: {'type': 'line', 'line': Line_2390044},\n", + " LVStation_119895: {'type': 'line', 'line': Line_2390046}},\n", + " BranchTee_MVGrid_239_42: {LVStation_119896: {'type': 'line',\n", + " 'line': Line_2390048},\n", + " LVStation_119900: {'type': 'line', 'line': Line_2390052},\n", + " BranchTee_MVGrid_239_43: {'type': 'line', 'line': Line_2390275}},\n", + " BranchTee_MVGrid_239_43: {LVStation_119901: {'type': 'line',\n", + " 'line': Line_2390053},\n", + " BranchTee_MVGrid_239_23: {'type': 'line', 'line': Line_2390256},\n", + " BranchTee_MVGrid_239_42: {'type': 'line', 'line': Line_2390275}},\n", + " BranchTee_MVGrid_239_44: {LVStation_119892: {'type': 'line',\n", + " 'line': Line_2390041},\n", + " LVStation_119893: {'type': 'line', 'line': Line_2390042},\n", + " LVStation_119895: {'type': 'line', 'line': Line_2390047},\n", + " LVStation_119896: {'type': 'line', 'line': Line_2390049},\n", + " BranchTee_MVGrid_239_93: {'type': 'line', 'line': Line_2390276}},\n", + " BranchTee_MVGrid_239_45: {LVStation_119903: {'type': 'line',\n", + " 'line': Line_2390054},\n", + " LVStation_119904: {'type': 'line', 'line': Line_2390056}},\n", + " BranchTee_MVGrid_239_46: {LVStation_120387: {'type': 'line',\n", + " 'line': Line_2390059},\n", + " LVStation_120390: {'type': 'line', 'line': Line_2390063}},\n", + " BranchTee_MVGrid_239_47: {LVStation_120555: {'type': 'line',\n", + " 'line': Line_2390066},\n", + " LVStation_500916: {'type': 'line', 'line': Line_2390235}},\n", + " BranchTee_MVGrid_239_48: {LVStation_120737: {'type': 'line',\n", + " 'line': Line_2390072},\n", + " LVStation_120738: {'type': 'line', 'line': Line_2390073}},\n", + " BranchTee_MVGrid_239_49: {LVStation_120853: {'type': 'line',\n", + " 'line': Line_2390075},\n", + " LVStation_511325: {'type': 'line', 'line': Line_2390239}},\n", + " BranchTee_MVGrid_239_50: {LVStation_120898: {'type': 'line',\n", + " 'line': Line_2390077},\n", + " LVStation_120899: {'type': 'line', 'line': Line_2390078}},\n", + " BranchTee_MVGrid_239_51: {LVStation_120942: {'type': 'line',\n", + " 'line': Line_2390079},\n", + " LVStation_120943: {'type': 'line', 'line': Line_2390081}},\n", + " BranchTee_MVGrid_239_52: {LVStation_121286: {'type': 'line',\n", + " 'line': Line_2390082},\n", + " LVStation_121287: {'type': 'line', 'line': Line_2390083},\n", + " LVStation_121288: {'type': 'line', 'line': Line_2390085}},\n", + " BranchTee_MVGrid_239_53: {LVStation_121317: {'type': 'line',\n", + " 'line': Line_2390088},\n", + " LVStation_121318: {'type': 'line', 'line': Line_2390090}},\n", + " BranchTee_MVGrid_239_54: {LVStation_121742: {'type': 'line',\n", + " 'line': Line_2390093},\n", + " LVStation_121743: {'type': 'line', 'line': Line_2390095},\n", + " BranchTee_MVGrid_239_28: {'type': 'line', 'line': Line_2390264}},\n", + " BranchTee_MVGrid_239_55: {LVStation_121741: {'type': 'line',\n", + " 'line': Line_2390092},\n", + " LVStation_121742: {'type': 'line', 'line': Line_2390094},\n", + " LVStation_122230: {'type': 'line', 'line': Line_2390124},\n", + " LVStation_496409: {'type': 'line', 'line': Line_2390233},\n", + " BranchTee_MVGrid_239_15: {'type': 'line', 'line': Line_2390247}},\n", + " BranchTee_MVGrid_239_56: {LVStation_121879: {'type': 'line',\n", + " 'line': Line_2390100},\n", + " LVStation_121880: {'type': 'line', 'line': Line_2390102}},\n", + " BranchTee_MVGrid_239_57: {LVStation_121915: {'type': 'line',\n", + " 'line': Line_2390105},\n", + " LVStation_121916: {'type': 'line', 'line': Line_2390107},\n", + " LVStation_121919: {'type': 'line', 'line': Line_2390109}},\n", + " BranchTee_MVGrid_239_58: {LVStation_121940: {'type': 'line',\n", + " 'line': Line_2390111},\n", + " LVStation_121941: {'type': 'line', 'line': Line_2390112}},\n", + " BranchTee_MVGrid_239_59: {LVStation_122076: {'type': 'line',\n", + " 'line': Line_2390113},\n", + " LVStation_122078: {'type': 'line', 'line': Line_2390118}},\n", + " BranchTee_MVGrid_239_60: {LVStation_122123: {'type': 'line',\n", + " 'line': Line_2390120},\n", + " LVStation_122124: {'type': 'line', 'line': Line_2390121},\n", + " LVStation_122125: {'type': 'line', 'line': Line_2390123}},\n", + " BranchTee_MVGrid_239_61: {LVStation_122230: {'type': 'line',\n", + " 'line': Line_2390125}},\n", + " BranchTee_MVGrid_239_62: {LVStation_122400: {'type': 'line',\n", + " 'line': Line_2390129},\n", + " LVStation_122401: {'type': 'line', 'line': Line_2390130}},\n", + " BranchTee_MVGrid_239_63: {LVStation_122408: {'type': 'line',\n", + " 'line': Line_2390131},\n", + " LVStation_485974: {'type': 'line', 'line': Line_2390228}},\n", + " BranchTee_MVGrid_239_64: {LVStation_122696: {'type': 'line',\n", + " 'line': Line_2390135},\n", + " BranchTee_MVGrid_239_26: {'type': 'line', 'line': Line_2390262},\n", + " BranchTee_MVGrid_239_66: {'type': 'line', 'line': Line_2390279}},\n", + " BranchTee_MVGrid_239_65: {LVStation_122698: {'type': 'line',\n", + " 'line': Line_2390138},\n", + " LVStation_122699: {'type': 'line', 'line': Line_2390139},\n", + " BranchTee_MVGrid_239_66: {'type': 'line', 'line': Line_2390280}},\n", + " BranchTee_MVGrid_239_66: {LVStation_122697: {'type': 'line',\n", + " 'line': Line_2390136},\n", + " LVStation_418254: {'type': 'line', 'line': Line_2390220},\n", + " BranchTee_MVGrid_239_64: {'type': 'line', 'line': Line_2390279},\n", + " BranchTee_MVGrid_239_65: {'type': 'line', 'line': Line_2390280},\n", + " BranchTee_MVGrid_239_90: {'type': 'line', 'line': Line_2390281}},\n", + " BranchTee_MVGrid_239_67: {LVStation_124010: {'type': 'line',\n", + " 'line': Line_2390141},\n", + " LVStation_124011: {'type': 'line', 'line': Line_2390143}},\n", + " BranchTee_MVGrid_239_68: {LVStation_124085: {'type': 'line',\n", + " 'line': Line_2390145},\n", + " LVStation_124086: {'type': 'line', 'line': Line_2390146}},\n", + " BranchTee_MVGrid_239_69: {LVStation_124109: {'type': 'line',\n", + " 'line': Line_2390147},\n", + " LVStation_124110: {'type': 'line', 'line': Line_2390149},\n", + " LVStation_124111: {'type': 'line', 'line': Line_2390151}},\n", + " BranchTee_MVGrid_239_70: {LVStation_498758: {'type': 'line',\n", + " 'line': Line_2390234},\n", + " BranchTee_MVGrid_239_24: {'type': 'line', 'line': Line_2390258},\n", + " BranchTee_MVGrid_239_71: {'type': 'line', 'line': Line_2390282}},\n", + " BranchTee_MVGrid_239_71: {LVStation_124582: {'type': 'line',\n", + " 'line': Line_2390154},\n", + " LVStation_124583: {'type': 'line', 'line': Line_2390156},\n", + " BranchTee_MVGrid_239_70: {'type': 'line', 'line': Line_2390282}},\n", + " BranchTee_MVGrid_239_72: {LVStation_124911: {'type': 'line',\n", + " 'line': Line_2390160}},\n", + " BranchTee_MVGrid_239_73: {LVStation_125016: {'type': 'line',\n", + " 'line': Line_2390163},\n", + " LVStation_500931: {'type': 'line', 'line': Line_2390236},\n", + " BranchTee_MVGrid_239_74: {'type': 'line', 'line': Line_2390283}},\n", + " BranchTee_MVGrid_239_74: {LVStation_125015: {'type': 'line',\n", + " 'line': Line_2390162},\n", + " LVStation_125017: {'type': 'line', 'line': Line_2390165},\n", + " BranchTee_MVGrid_239_73: {'type': 'line', 'line': Line_2390283}},\n", + " BranchTee_MVGrid_239_75: {LVStation_125210: {'type': 'line',\n", + " 'line': Line_2390166},\n", + " LVStation_125211: {'type': 'line', 'line': Line_2390169},\n", + " MVDisconnectingPoint_4: {'line': Line_2390284, 'type': 'line'}},\n", + " BranchTee_MVGrid_239_76: {LVStation_125214: {'type': 'line',\n", + " 'line': Line_2390172},\n", + " LVStation_125215: {'type': 'line', 'line': Line_2390174},\n", + " BranchTee_MVGrid_239_25: {'type': 'line', 'line': Line_2390261}},\n", + " BranchTee_MVGrid_239_77: {LVStation_124911: {'type': 'line',\n", + " 'line': Line_2390161},\n", + " LVStation_125213: {'type': 'line', 'line': Line_2390171},\n", + " LVStation_125214: {'type': 'line', 'line': Line_2390173}},\n", + " BranchTee_MVGrid_239_78: {LVStation_125267: {'type': 'line',\n", + " 'line': Line_2390178},\n", + " LVStation_125268: {'type': 'line', 'line': Line_2390179},\n", + " BranchTee_MVGrid_239_27: {'type': 'line', 'line': Line_2390263}},\n", + " BranchTee_MVGrid_239_79: {LVStation_125268: {'type': 'line',\n", + " 'line': Line_2390180},\n", + " LVStation_125269: {'type': 'line', 'line': Line_2390182}},\n", + " BranchTee_MVGrid_239_80: {LVStation_139104: {'type': 'line',\n", + " 'line': Line_2390185},\n", + " LVStation_139105: {'type': 'line', 'line': Line_2390186},\n", + " LVStation_139106: {'type': 'line', 'line': Line_2390187}},\n", + " BranchTee_MVGrid_239_81: {LVStation_139150: {'type': 'line',\n", + " 'line': Line_2390192}},\n", + " BranchTee_MVGrid_239_82: {LVStation_139183: {'type': 'line',\n", + " 'line': Line_2390195},\n", + " LVStation_488816: {'type': 'line', 'line': Line_2390231},\n", + " LVStation_490253: {'type': 'line', 'line': Line_2390232}},\n", + " BranchTee_MVGrid_239_83: {LVStation_139186: {'type': 'line',\n", + " 'line': Line_2390199},\n", + " LVStation_139187: {'type': 'line', 'line': Line_2390201},\n", + " MVDisconnectingPoint_5: {'line': Line_2390197, 'type': 'line'}},\n", + " BranchTee_MVGrid_239_84: {GeneratorFluctuating_878583: {'type': 'line',\n", + " 'line': Line_2390001},\n", + " LVStation_120738: {'type': 'line', 'line': Line_2390074},\n", + " BranchTee_MVGrid_239_12: {'type': 'line', 'line': Line_2390244}},\n", + " BranchTee_MVGrid_239_85: {GeneratorFluctuating_878963: {'type': 'line',\n", + " 'line': Line_2390002},\n", + " LVStation_416815: {'type': 'line', 'line': Line_2390208},\n", + " BranchTee_MVGrid_239_24: {'type': 'line', 'line': Line_2390259}},\n", + " BranchTee_MVGrid_239_86: {GeneratorFluctuating_839361: {'type': 'line',\n", + " 'line': Line_2390004},\n", + " LVStation_139107: {'type': 'line', 'line': Line_2390188},\n", + " BranchTee_MVGrid_239_33: {'type': 'line', 'line': Line_2390272}},\n", + " BranchTee_MVGrid_239_87: {GeneratorFluctuating_839362: {'type': 'line',\n", + " 'line': Line_2390005},\n", + " LVStation_119698: {'type': 'line', 'line': Line_2390030},\n", + " LVStation_119889: {'type': 'line', 'line': Line_2390037}},\n", + " BranchTee_MVGrid_239_88: {GeneratorFluctuating_839363: {'type': 'line',\n", + " 'line': Line_2390006},\n", + " LVStation_125210: {'type': 'line', 'line': Line_2390167},\n", + " BranchTee_MVGrid_239_3: {'type': 'line', 'line': Line_2390273}},\n", + " BranchTee_MVGrid_239_89: {GeneratorFluctuating_878450: {'type': 'line',\n", + " 'line': Line_2390008},\n", + " LVStation_418546: {'type': 'line', 'line': Line_2390221},\n", + " BranchTee_MVGrid_239_3: {'type': 'line', 'line': Line_2390274}},\n", + " BranchTee_MVGrid_239_90: {GeneratorFluctuating_878862: {'type': 'line',\n", + " 'line': Line_2390013},\n", + " LVStation_123655: {'type': 'line', 'line': Line_2390140},\n", + " BranchTee_MVGrid_239_66: {'type': 'line', 'line': Line_2390281}},\n", + " BranchTee_MVGrid_239_91: {GeneratorFluctuating_878863: {'type': 'line',\n", + " 'line': Line_2390014},\n", + " LVStation_122520: {'type': 'line', 'line': Line_2390134},\n", + " BranchTee_MVGrid_239_30: {'type': 'line', 'line': Line_2390269}},\n", + " BranchTee_MVGrid_239_92: {GeneratorFluctuating_878864: {'type': 'line',\n", + " 'line': Line_2390015},\n", + " LVStation_119897: {'type': 'line', 'line': Line_2390051},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390286}},\n", + " BranchTee_MVGrid_239_93: {GeneratorFluctuating_878865: {'type': 'line',\n", + " 'line': Line_2390016},\n", + " LVStation_120038: {'type': 'line', 'line': Line_2390057},\n", + " BranchTee_MVGrid_239_44: {'type': 'line', 'line': Line_2390276}},\n", + " BranchTee_MVGrid_239_94: {GeneratorFluctuating_878866: {'type': 'line',\n", + " 'line': Line_2390017},\n", + " LVStation_124910: {'type': 'line', 'line': Line_2390159},\n", + " LVStation_125216: {'type': 'line', 'line': Line_2390175}},\n", + " LVStation_122408: {BranchTee_MVGrid_239_63: {'type': 'line',\n", + " 'line': Line_2390131}},\n", + " LVStation_485974: {BranchTee_MVGrid_239_63: {'type': 'line',\n", + " 'line': Line_2390228},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390229}},\n", + " LVStation_138585: {LVStation_139149: {'type': 'line', 'line': Line_2390183}},\n", + " LVStation_119895: {LVStation_119899: {'type': 'line', 'line': Line_2390045},\n", + " BranchTee_MVGrid_239_41: {'type': 'line', 'line': Line_2390046},\n", + " BranchTee_MVGrid_239_44: {'type': 'line', 'line': Line_2390047}},\n", + " LVStation_119896: {BranchTee_MVGrid_239_42: {'type': 'line',\n", + " 'line': Line_2390048},\n", + " BranchTee_MVGrid_239_44: {'type': 'line', 'line': Line_2390049}},\n", + " LVStation_119889: {LVStation_119891: {'type': 'line', 'line': Line_2390036},\n", + " BranchTee_MVGrid_239_87: {'type': 'line', 'line': Line_2390037}},\n", + " LVStation_119890: {LVStation_119893: {'type': 'line', 'line': Line_2390038},\n", + " LVStation_416175: {'type': 'line', 'line': Line_2390039}},\n", + " LVStation_119891: {LVStation_119889: {'type': 'line', 'line': Line_2390036},\n", + " BranchTee_MVGrid_239_41: {'type': 'line', 'line': Line_2390040}},\n", + " LVStation_119892: {LVStation_119697: {'type': 'line', 'line': Line_2390027},\n", + " BranchTee_MVGrid_239_44: {'type': 'line', 'line': Line_2390041}},\n", + " LVStation_119893: {LVStation_119890: {'type': 'line', 'line': Line_2390038},\n", + " BranchTee_MVGrid_239_44: {'type': 'line', 'line': Line_2390042}},\n", + " LVStation_119894: {LVStation_119898: {'type': 'line', 'line': Line_2390043},\n", + " BranchTee_MVGrid_239_41: {'type': 'line', 'line': Line_2390044}},\n", + " LVStation_119897: {BranchTee_MVGrid_239_1: {'type': 'line',\n", + " 'line': Line_2390050},\n", + " BranchTee_MVGrid_239_92: {'type': 'line', 'line': Line_2390051}},\n", + " LVStation_119898: {LVStation_119894: {'type': 'line', 'line': Line_2390043}},\n", + " LVStation_119899: {LVStation_119895: {'type': 'line', 'line': Line_2390045}},\n", + " LVStation_119900: {BranchTee_MVGrid_239_42: {'type': 'line',\n", + " 'line': Line_2390052}},\n", + " LVStation_119901: {BranchTee_MVGrid_239_43: {'type': 'line',\n", + " 'line': Line_2390053}},\n", + " LVStation_417530: {BranchTee_MVGrid_239_14: {'type': 'line',\n", + " 'line': Line_2390211}},\n", + " LVStation_419885: {BranchTee_MVGrid_239_12: {'type': 'line',\n", + " 'line': Line_2390226},\n", + " BranchTee_MVGrid_239_33: {'type': 'line', 'line': Line_2390227}},\n", + " LVStation_121940: {BranchTee_MVGrid_239_18: {'type': 'line',\n", + " 'line': Line_2390110},\n", + " BranchTee_MVGrid_239_58: {'type': 'line', 'line': Line_2390111}},\n", + " LVStation_121941: {BranchTee_MVGrid_239_58: {'type': 'line',\n", + " 'line': Line_2390112}},\n", + " LVStation_122426: {BranchTee_MVGrid_239_28: {'type': 'line',\n", + " 'line': Line_2390132}},\n", + " LVStation_122480: {BranchTee_MVGrid_239_29: {'type': 'line',\n", + " 'line': Line_2390133}},\n", + " LVStation_418254: {LVStation_124543: {'type': 'line', 'line': Line_2390152},\n", + " BranchTee_MVGrid_239_66: {'type': 'line', 'line': Line_2390220}},\n", + " LVStation_419605: {LVStation_125217: {'type': 'line', 'line': Line_2390176}},\n", + " LVStation_416441: {BranchTee_MVGrid_239_13: {'type': 'line',\n", + " 'line': Line_2390204}},\n", + " LVStation_418546: {BranchTee_MVGrid_239_89: {'type': 'line',\n", + " 'line': Line_2390221}},\n", + " LVStation_416244: {LVStation_119697: {'type': 'line', 'line': Line_2390028}},\n", + " LVStation_417898: {LVStation_417550: {'type': 'line', 'line': Line_2390212},\n", + " BranchTee_MVGrid_239_38: {'type': 'line', 'line': Line_2390214}},\n", + " LVStation_419795: {BranchTee_MVGrid_239_8: {'type': 'line',\n", + " 'line': Line_2390225}},\n", + " LVStation_120737: {LVStation_120736: {'type': 'line', 'line': Line_2390070},\n", + " BranchTee_MVGrid_239_48: {'type': 'line', 'line': Line_2390072}},\n", + " LVStation_120736: {LVStation_120737: {'type': 'line', 'line': Line_2390070},\n", + " BranchTee_MVGrid_239_5: {'type': 'line', 'line': Line_2390071}},\n", + " LVStation_120738: {BranchTee_MVGrid_239_48: {'type': 'line',\n", + " 'line': Line_2390073},\n", + " BranchTee_MVGrid_239_84: {'type': 'line', 'line': Line_2390074}},\n", + " LVStation_120942: {BranchTee_MVGrid_239_51: {'type': 'line',\n", + " 'line': Line_2390079}},\n", + " LVStation_120943: {BranchTee_MVGrid_239_12: {'type': 'line',\n", + " 'line': Line_2390080},\n", + " BranchTee_MVGrid_239_51: {'type': 'line', 'line': Line_2390081}},\n", + " LVStation_122230: {BranchTee_MVGrid_239_55: {'type': 'line',\n", + " 'line': Line_2390124},\n", + " BranchTee_MVGrid_239_61: {'type': 'line', 'line': Line_2390125}},\n", + " LVStation_122231: {LVStation_139192: {'type': 'line', 'line': Line_2390126},\n", + " BranchTee_MVGrid_239_35: {'type': 'line', 'line': Line_2390127}},\n", + " LVStation_418237: {BranchTee_MVGrid_239_22: {'type': 'line',\n", + " 'line': Line_2390218}},\n", + " LVStation_416449: {BranchTee_MVGrid_239_24: {'type': 'line',\n", + " 'line': Line_2390205}},\n", + " LVStation_417550: {LVStation_417898: {'type': 'line', 'line': Line_2390212},\n", + " BranchTee_MVGrid_239_26: {'type': 'line', 'line': Line_2390213}},\n", + " LVStation_139107: {BranchTee_MVGrid_239_86: {'type': 'line',\n", + " 'line': Line_2390188}},\n", + " LVStation_120585: {LVStation_124583: {'type': 'line', 'line': Line_2390068},\n", + " BranchTee_MVGrid_239_9: {'type': 'line', 'line': Line_2390069}},\n", + " LVStation_417276: {BranchTee_MVGrid_239_16: {'type': 'line',\n", + " 'line': Line_2390210}},\n", + " LVStation_122520: {BranchTee_MVGrid_239_91: {'type': 'line',\n", + " 'line': Line_2390134}},\n", + " LVStation_419726: {BranchTee_MVGrid_239_7: {'type': 'line',\n", + " 'line': Line_2390224}},\n", + " LVStation_121776: {BranchTee_MVGrid_239_15: {'type': 'line',\n", + " 'line': Line_2390096}},\n", + " LVStation_419327: {LVStation_124910: {'type': 'line', 'line': Line_2390158}},\n", + " LVStation_417734: {LVStation_139189: {'type': 'line', 'line': Line_2390203}},\n", + " LVStation_125015: {BranchTee_MVGrid_239_74: {'type': 'line',\n", + " 'line': Line_2390162}},\n", + " LVStation_125016: {LVStation_120389: {'type': 'line', 'line': Line_2390062},\n", + " BranchTee_MVGrid_239_73: {'type': 'line', 'line': Line_2390163}},\n", + " LVStation_125017: {LVStation_417909: {'type': 'line', 'line': Line_2390164},\n", + " BranchTee_MVGrid_239_74: {'type': 'line', 'line': Line_2390165}},\n", + " LVStation_500931: {BranchTee_MVGrid_239_73: {'type': 'line',\n", + " 'line': Line_2390236}},\n", + " LVStation_418244: {LVStation_122698: {'type': 'line', 'line': Line_2390137},\n", + " BranchTee_MVGrid_239_11: {'type': 'line', 'line': Line_2390219}},\n", + " LVStation_120411: {BranchTee_MVGrid_239_6: {'type': 'line',\n", + " 'line': Line_2390064}},\n", + " LVStation_121317: {BranchTee_MVGrid_239_13: {'type': 'line',\n", + " 'line': Line_2390087},\n", + " BranchTee_MVGrid_239_53: {'type': 'line', 'line': Line_2390088}},\n", + " LVStation_121318: {LVStation_121918: {'type': 'line', 'line': Line_2390089},\n", + " BranchTee_MVGrid_239_53: {'type': 'line', 'line': Line_2390090}},\n", + " LVStation_416815: {BranchTee_MVGrid_239_17: {'type': 'line',\n", + " 'line': Line_2390207},\n", + " BranchTee_MVGrid_239_85: {'type': 'line', 'line': Line_2390208}},\n", + " LVStation_139104: {BranchTee_MVGrid_239_32: {'type': 'line',\n", + " 'line': Line_2390184},\n", + " BranchTee_MVGrid_239_80: {'type': 'line', 'line': Line_2390185}},\n", + " LVStation_139105: {BranchTee_MVGrid_239_80: {'type': 'line',\n", + " 'line': Line_2390186}},\n", + " LVStation_139106: {BranchTee_MVGrid_239_80: {'type': 'line',\n", + " 'line': Line_2390187}},\n", + " LVStation_139192: {LVStation_122231: {'type': 'line', 'line': Line_2390126}},\n", + " LVStation_119903: {BranchTee_MVGrid_239_45: {'type': 'line',\n", + " 'line': Line_2390054}},\n", + " LVStation_119904: {BranchTee_MVGrid_239_4: {'type': 'line',\n", + " 'line': Line_2390055},\n", + " BranchTee_MVGrid_239_45: {'type': 'line', 'line': Line_2390056}},\n", + " LVStation_418449: {LVStation_121741: {'type': 'line', 'line': Line_2390091}},\n", + " LVStation_419079: {BranchTee_MVGrid_239_20: {'type': 'line',\n", + " 'line': Line_2390223}},\n", + " LVStation_119697: {LVStation_119892: {'type': 'line', 'line': Line_2390027},\n", + " LVStation_416244: {'type': 'line', 'line': Line_2390028}},\n", + " LVStation_119698: {BranchTee_MVGrid_239_39: {'type': 'line',\n", + " 'line': Line_2390029},\n", + " BranchTee_MVGrid_239_87: {'type': 'line', 'line': Line_2390030}},\n", + " LVStation_122076: {BranchTee_MVGrid_239_59: {'type': 'line',\n", + " 'line': Line_2390113},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390114}},\n", + " LVStation_122077: {BranchTee_MVGrid_239_22: {'type': 'line',\n", + " 'line': Line_2390115},\n", + " BranchTee_MVGrid_239_28: {'type': 'line', 'line': Line_2390116}},\n", + " LVStation_122078: {BranchTee_MVGrid_239_22: {'type': 'line',\n", + " 'line': Line_2390117},\n", + " BranchTee_MVGrid_239_59: {'type': 'line', 'line': Line_2390118}},\n", + " LVStation_122124: {LVStation_121878: {'type': 'line', 'line': Line_2390097},\n", + " BranchTee_MVGrid_239_60: {'type': 'line', 'line': Line_2390121}},\n", + " LVStation_122125: {LVStation_490253: {'type': 'line', 'line': Line_2390122},\n", + " BranchTee_MVGrid_239_60: {'type': 'line', 'line': Line_2390123}},\n", + " LVStation_122122: {LVStation_122123: {'type': 'line', 'line': Line_2390119}},\n", + " LVStation_122123: {LVStation_122122: {'type': 'line', 'line': Line_2390119},\n", + " BranchTee_MVGrid_239_60: {'type': 'line', 'line': Line_2390120}},\n", + " LVStation_124543: {LVStation_418254: {'type': 'line', 'line': Line_2390152}},\n", + " LVStation_124911: {BranchTee_MVGrid_239_72: {'type': 'line',\n", + " 'line': Line_2390160},\n", + " BranchTee_MVGrid_239_77: {'type': 'line', 'line': Line_2390161}},\n", + " LVStation_124910: {LVStation_419327: {'type': 'line', 'line': Line_2390158},\n", + " BranchTee_MVGrid_239_94: {'type': 'line', 'line': Line_2390159}},\n", + " LVStation_139183: {LVStation_139184: {'type': 'line', 'line': Line_2390194},\n", + " BranchTee_MVGrid_239_82: {'type': 'line', 'line': Line_2390195}},\n", + " LVStation_139184: {LVStation_139183: {'type': 'line', 'line': Line_2390194},\n", + " LVStation_139185: {'type': 'line', 'line': Line_2390196}},\n", + " LVStation_139185: {LVStation_139184: {'type': 'line', 'line': Line_2390196}},\n", + " LVStation_139186: {BranchTee_MVGrid_239_31: {'type': 'line',\n", + " 'line': Line_2390198},\n", + " BranchTee_MVGrid_239_83: {'type': 'line', 'line': Line_2390199}},\n", + " LVStation_139187: {LVStation_139188: {'type': 'line', 'line': Line_2390200},\n", + " BranchTee_MVGrid_239_83: {'type': 'line', 'line': Line_2390201}},\n", + " LVStation_139188: {LVStation_139187: {'type': 'line', 'line': Line_2390200},\n", + " LVStation_139189: {'type': 'line', 'line': Line_2390202}},\n", + " LVStation_139189: {LVStation_139188: {'type': 'line', 'line': Line_2390202},\n", + " LVStation_417734: {'type': 'line', 'line': Line_2390203}},\n", + " LVStation_488816: {LVStation_490252: {'type': 'line', 'line': Line_2390230},\n", + " BranchTee_MVGrid_239_82: {'type': 'line', 'line': Line_2390231}},\n", + " LVStation_490252: {LVStation_488816: {'type': 'line', 'line': Line_2390230}},\n", + " LVStation_490253: {LVStation_122125: {'type': 'line', 'line': Line_2390122},\n", + " BranchTee_MVGrid_239_82: {'type': 'line', 'line': Line_2390232}},\n", + " LVStation_118322: {BranchTee_MVGrid_239_36: {'type': 'line',\n", + " 'line': Line_2390020}},\n", + " LVStation_118323: {BranchTee_MVGrid_239_36: {'type': 'line',\n", + " 'line': Line_2390021},\n", + " MVDisconnectingPoint_3: {'line': Line_2390022, 'type': 'line'}},\n", + " LVStation_118324: {BranchTee_MVGrid_239_37: {'type': 'line',\n", + " 'line': Line_2390023}},\n", + " LVStation_515314: {LVStation_119702: {'type': 'line', 'line': Line_2390033},\n", + " BranchTee_MVGrid_239_37: {'type': 'line', 'line': Line_2390240}},\n", + " LVStation_120387: {LVStation_120388: {'type': 'line', 'line': Line_2390058},\n", + " BranchTee_MVGrid_239_46: {'type': 'line', 'line': Line_2390059}},\n", + " LVStation_120388: {LVStation_120387: {'type': 'line', 'line': Line_2390058},\n", + " LVStation_121287: {'type': 'line', 'line': Line_2390060}},\n", + " LVStation_120389: {LVStation_120390: {'type': 'line', 'line': Line_2390061},\n", + " LVStation_125016: {'type': 'line', 'line': Line_2390062}},\n", + " LVStation_120390: {LVStation_120389: {'type': 'line', 'line': Line_2390061},\n", + " BranchTee_MVGrid_239_46: {'type': 'line', 'line': Line_2390063}},\n", + " LVStation_120853: {BranchTee_MVGrid_239_49: {'type': 'line',\n", + " 'line': Line_2390075}},\n", + " LVStation_511325: {BranchTee_MVGrid_239_10: {'type': 'line',\n", + " 'line': Line_2390238},\n", + " BranchTee_MVGrid_239_49: {'type': 'line', 'line': Line_2390239}},\n", + " LVStation_120470: {BranchTee_MVGrid_239_7: {'type': 'line',\n", + " 'line': Line_2390065}},\n", + " LVStation_417987: {BranchTee_MVGrid_239_27: {'type': 'line',\n", + " 'line': Line_2390217}},\n", + " LVStation_119612: {GeneratorFluctuating_839364: {'type': 'line',\n", + " 'line': Line_2390007},\n", + " BranchTee_MVGrid_239_38: {'type': 'line', 'line': Line_2390024}},\n", + " LVStation_119613: {LVStation_119703: {'type': 'line', 'line': Line_2390025},\n", + " BranchTee_MVGrid_239_38: {'type': 'line', 'line': Line_2390026}},\n", + " LVStation_119701: {LVStation_119702: {'type': 'line', 'line': Line_2390031},\n", + " BranchTee_MVGrid_239_40: {'type': 'line', 'line': Line_2390032}},\n", + " LVStation_119702: {LVStation_119701: {'type': 'line', 'line': Line_2390031},\n", + " LVStation_515314: {'type': 'line', 'line': Line_2390033}},\n", + " LVStation_119703: {LVStation_119613: {'type': 'line', 'line': Line_2390025},\n", + " LVStation_119704: {'type': 'line', 'line': Line_2390034}},\n", + " LVStation_119704: {LVStation_119703: {'type': 'line', 'line': Line_2390034},\n", + " BranchTee_MVGrid_239_40: {'type': 'line', 'line': Line_2390035}},\n", + " LVStation_120038: {BranchTee_MVGrid_239_93: {'type': 'line',\n", + " 'line': Line_2390057}},\n", + " LVStation_120555: {BranchTee_MVGrid_239_47: {'type': 'line',\n", + " 'line': Line_2390066},\n", + " BranchTee_MVGrid_239_9: {'type': 'line', 'line': Line_2390067}},\n", + " LVStation_500916: {BranchTee_MVGrid_239_47: {'type': 'line',\n", + " 'line': Line_2390235}},\n", + " LVStation_418547: {LVStation_496409: {'type': 'line', 'line': Line_2390222}},\n", + " LVStation_121286: {BranchTee_MVGrid_239_52: {'type': 'line',\n", + " 'line': Line_2390082}},\n", + " LVStation_121287: {LVStation_120388: {'type': 'line', 'line': Line_2390060},\n", + " BranchTee_MVGrid_239_52: {'type': 'line', 'line': Line_2390083}},\n", + " LVStation_121288: {LVStation_121289: {'type': 'line', 'line': Line_2390084},\n", + " BranchTee_MVGrid_239_52: {'type': 'line', 'line': Line_2390085}},\n", + " LVStation_121289: {LVStation_121288: {'type': 'line', 'line': Line_2390084},\n", + " BranchTee_MVGrid_239_14: {'type': 'line', 'line': Line_2390086}},\n", + " LVStation_121741: {LVStation_418449: {'type': 'line', 'line': Line_2390091},\n", + " BranchTee_MVGrid_239_55: {'type': 'line', 'line': Line_2390092}},\n", + " LVStation_121742: {BranchTee_MVGrid_239_54: {'type': 'line',\n", + " 'line': Line_2390093},\n", + " BranchTee_MVGrid_239_55: {'type': 'line', 'line': Line_2390094}},\n", + " LVStation_121743: {BranchTee_MVGrid_239_54: {'type': 'line',\n", + " 'line': Line_2390095}},\n", + " LVStation_496409: {LVStation_418547: {'type': 'line', 'line': Line_2390222},\n", + " BranchTee_MVGrid_239_55: {'type': 'line', 'line': Line_2390233}},\n", + " LVStation_416983: {BranchTee_MVGrid_239_17: {'type': 'line',\n", + " 'line': Line_2390209}},\n", + " LVStation_121878: {LVStation_122124: {'type': 'line', 'line': Line_2390097},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390098}},\n", + " LVStation_121879: {BranchTee_MVGrid_239_21: {'type': 'line',\n", + " 'line': Line_2390099},\n", + " BranchTee_MVGrid_239_56: {'type': 'line', 'line': Line_2390100}},\n", + " LVStation_121880: {LVStation_496410: {'type': 'line', 'line': Line_2390101},\n", + " BranchTee_MVGrid_239_56: {'type': 'line', 'line': Line_2390102},\n", + " MVStation_239: {'type': 'line', 'line': Line_2390103}},\n", + " LVStation_496410: {LVStation_121880: {'type': 'line', 'line': Line_2390101}},\n", + " LVStation_121915: {LVStation_121918: {'type': 'line', 'line': Line_2390104},\n", + " BranchTee_MVGrid_239_57: {'type': 'line', 'line': Line_2390105}},\n", + " LVStation_121916: {LVStation_121917: {'type': 'line', 'line': Line_2390106},\n", + " BranchTee_MVGrid_239_57: {'type': 'line', 'line': Line_2390107}},\n", + " LVStation_121917: {LVStation_121916: {'type': 'line', 'line': Line_2390106}},\n", + " LVStation_121918: {LVStation_121318: {'type': 'line', 'line': Line_2390089},\n", + " LVStation_121915: {'type': 'line', 'line': Line_2390104}},\n", + " LVStation_121919: {BranchTee_MVGrid_239_19: {'type': 'line',\n", + " 'line': Line_2390108},\n", + " BranchTee_MVGrid_239_57: {'type': 'line', 'line': Line_2390109}},\n", + " LVStation_416589: {BranchTee_MVGrid_239_19: {'type': 'line',\n", + " 'line': Line_2390206}},\n", + " LVStation_122400: {BranchTee_MVGrid_239_21: {'type': 'line',\n", + " 'line': Line_2390128},\n", + " BranchTee_MVGrid_239_62: {'type': 'line', 'line': Line_2390129}},\n", + " LVStation_122401: {BranchTee_MVGrid_239_62: {'type': 'line',\n", + " 'line': Line_2390130}},\n", + " LVStation_122696: {BranchTee_MVGrid_239_64: {'type': 'line',\n", + " 'line': Line_2390135}},\n", + " LVStation_122697: {BranchTee_MVGrid_239_66: {'type': 'line',\n", + " 'line': Line_2390136}},\n", + " LVStation_122698: {LVStation_418244: {'type': 'line', 'line': Line_2390137},\n", + " BranchTee_MVGrid_239_65: {'type': 'line', 'line': Line_2390138}},\n", + " LVStation_122699: {BranchTee_MVGrid_239_65: {'type': 'line',\n", + " 'line': Line_2390139}},\n", + " LVStation_123655: {BranchTee_MVGrid_239_90: {'type': 'line',\n", + " 'line': Line_2390140}},\n", + " LVStation_124010: {BranchTee_MVGrid_239_67: {'type': 'line',\n", + " 'line': Line_2390141}},\n", + " LVStation_124011: {LVStation_124109: {'type': 'line', 'line': Line_2390142},\n", + " BranchTee_MVGrid_239_67: {'type': 'line', 'line': Line_2390143}},\n", + " LVStation_124109: {LVStation_124011: {'type': 'line', 'line': Line_2390142},\n", + " BranchTee_MVGrid_239_69: {'type': 'line', 'line': Line_2390147}},\n", + " LVStation_124110: {BranchTee_MVGrid_239_17: {'type': 'line',\n", + " 'line': Line_2390148},\n", + " BranchTee_MVGrid_239_69: {'type': 'line', 'line': Line_2390149}},\n", + " LVStation_124111: {BranchTee_MVGrid_239_36: {'type': 'line',\n", + " 'line': Line_2390150},\n", + " BranchTee_MVGrid_239_69: {'type': 'line', 'line': Line_2390151}},\n", + " LVStation_417936: {LVStation_124902: {'type': 'line', 'line': Line_2390157},\n", + " BranchTee_MVGrid_239_26: {'type': 'line', 'line': Line_2390216}},\n", + " LVStation_124902: {LVStation_417936: {'type': 'line', 'line': Line_2390157}},\n", + " LVStation_416175: {LVStation_119890: {'type': 'line', 'line': Line_2390039}},\n", + " LVStation_125210: {BranchTee_MVGrid_239_75: {'type': 'line',\n", + " 'line': Line_2390166},\n", + " BranchTee_MVGrid_239_88: {'type': 'line', 'line': Line_2390167}},\n", + " LVStation_125211: {LVStation_125212: {'type': 'line', 'line': Line_2390168},\n", + " BranchTee_MVGrid_239_75: {'type': 'line', 'line': Line_2390169}},\n", + " LVStation_125212: {LVStation_125211: {'type': 'line', 'line': Line_2390168}},\n", + " LVStation_125213: {LVStation_125216: {'type': 'line', 'line': Line_2390170},\n", + " BranchTee_MVGrid_239_77: {'type': 'line', 'line': Line_2390171}},\n", + " LVStation_125214: {BranchTee_MVGrid_239_76: {'type': 'line',\n", + " 'line': Line_2390172},\n", + " BranchTee_MVGrid_239_77: {'type': 'line', 'line': Line_2390173}},\n", + " LVStation_125215: {BranchTee_MVGrid_239_76: {'type': 'line',\n", + " 'line': Line_2390174}},\n", + " LVStation_125216: {LVStation_125213: {'type': 'line', 'line': Line_2390170},\n", + " BranchTee_MVGrid_239_94: {'type': 'line', 'line': Line_2390175}},\n", + " LVStation_125217: {LVStation_419605: {'type': 'line', 'line': Line_2390176},\n", + " LVStation_503036: {'type': 'line', 'line': Line_2390177}},\n", + " LVStation_503036: {LVStation_125217: {'type': 'line', 'line': Line_2390177},\n", + " BranchTee_MVGrid_239_25: {'type': 'line', 'line': Line_2390237}},\n", + " LVStation_125269: {BranchTee_MVGrid_239_3: {'type': 'line',\n", + " 'line': Line_2390181},\n", + " BranchTee_MVGrid_239_79: {'type': 'line', 'line': Line_2390182}},\n", + " LVStation_125267: {BranchTee_MVGrid_239_78: {'type': 'line',\n", + " 'line': Line_2390178}},\n", + " LVStation_125268: {BranchTee_MVGrid_239_78: {'type': 'line',\n", + " 'line': Line_2390179},\n", + " BranchTee_MVGrid_239_79: {'type': 'line', 'line': Line_2390180}},\n", + " LVStation_120898: {BranchTee_MVGrid_239_11: {'type': 'line',\n", + " 'line': Line_2390076},\n", + " BranchTee_MVGrid_239_50: {'type': 'line', 'line': Line_2390077}},\n", + " LVStation_120899: {BranchTee_MVGrid_239_50: {'type': 'line',\n", + " 'line': Line_2390078}},\n", + " LVStation_139149: {LVStation_138585: {'type': 'line', 'line': Line_2390183},\n", + " BranchTee_MVGrid_239_31: {'type': 'line', 'line': Line_2390189}},\n", + " LVStation_139150: {LVStation_139151: {'type': 'line', 'line': Line_2390190},\n", + " BranchTee_MVGrid_239_34: {'type': 'line', 'line': Line_2390191},\n", + " BranchTee_MVGrid_239_81: {'type': 'line', 'line': Line_2390192}},\n", + " LVStation_139151: {LVStation_139150: {'type': 'line', 'line': Line_2390190},\n", + " LVStation_139152: {'type': 'line', 'line': Line_2390193}},\n", + " LVStation_139152: {LVStation_139151: {'type': 'line', 'line': Line_2390193}},\n", + " LVStation_417909: {LVStation_125017: {'type': 'line', 'line': Line_2390164},\n", + " BranchTee_MVGrid_239_27: {'type': 'line', 'line': Line_2390215}},\n", + " LVStation_124085: {BranchTee_MVGrid_239_23: {'type': 'line',\n", + " 'line': Line_2390144},\n", + " BranchTee_MVGrid_239_68: {'type': 'line', 'line': Line_2390145}},\n", + " LVStation_124086: {BranchTee_MVGrid_239_68: {'type': 'line',\n", + " 'line': Line_2390146}},\n", + " LVStation_124581: {LVStation_124582: {'type': 'line', 'line': Line_2390153}},\n", + " LVStation_124582: {LVStation_124581: {'type': 'line', 'line': Line_2390153},\n", + " BranchTee_MVGrid_239_71: {'type': 'line', 'line': Line_2390154}},\n", + " LVStation_124583: {LVStation_120585: {'type': 'line', 'line': Line_2390068},\n", + " LVStation_124584: {'type': 'line', 'line': Line_2390155},\n", + " BranchTee_MVGrid_239_71: {'type': 'line', 'line': Line_2390156}},\n", + " LVStation_124584: {LVStation_124583: {'type': 'line', 'line': Line_2390155}},\n", + " LVStation_498758: {BranchTee_MVGrid_239_70: {'type': 'line',\n", + " 'line': Line_2390234}},\n", + " MVStation_239: {GeneratorFluctuating_878609: {'type': 'line',\n", + " 'line': Line_2390009},\n", + " GeneratorFluctuating_878611: {'type': 'line', 'line': Line_2390010},\n", + " GeneratorFluctuating_878614: {'type': 'line', 'line': Line_2390011},\n", + " GeneratorFluctuating_878615: {'type': 'line', 'line': Line_2390012},\n", + " GeneratorFluctuating_878875: {'type': 'line', 'line': Line_2390018},\n", + " GeneratorFluctuating_878950: {'type': 'line', 'line': Line_2390019},\n", + " LVStation_121878: {'type': 'line', 'line': Line_2390098},\n", + " LVStation_121880: {'type': 'line', 'line': Line_2390103},\n", + " LVStation_122076: {'type': 'line', 'line': Line_2390114},\n", + " LVStation_485974: {'type': 'line', 'line': Line_2390229},\n", + " BranchTee_MVGrid_239_11: {'type': 'line', 'line': Line_2390243},\n", + " BranchTee_MVGrid_239_14: {'type': 'line', 'line': Line_2390245},\n", + " BranchTee_MVGrid_239_16: {'type': 'line', 'line': Line_2390249},\n", + " BranchTee_MVGrid_239_23: {'type': 'line', 'line': Line_2390257},\n", + " BranchTee_MVGrid_239_2: {'type': 'line', 'line': Line_2390266},\n", + " BranchTee_MVGrid_239_92: {'type': 'line', 'line': Line_2390286}},\n", + " MVDisconnectingPoint_1: {BranchTee_MVGrid_239_1: {'line': Line_2390252,\n", + " 'type': 'line'}},\n", + " MVDisconnectingPoint_2: {BranchTee_MVGrid_239_2: {'line': Line_2390265,\n", + " 'type': 'line'}},\n", + " MVDisconnectingPoint_3: {LVStation_118323: {'line': Line_2390022,\n", + " 'type': 'line'}},\n", + " MVDisconnectingPoint_4: {BranchTee_MVGrid_239_75: {'line': Line_2390284,\n", + " 'type': 'line'}},\n", + " MVDisconnectingPoint_5: {BranchTee_MVGrid_239_83: {'line': Line_2390197,\n", + " 'type': 'line'}}}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get a dictionary of all lines in the mv grid\n", + "edisgo.network.mv_grid.graph.edge" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The dictionary you got should look something like that:\n", + "```python\n", + "{Generator_x: {BranchTee_y: {'type': 'line', 'line': Line_1}},\n", + " BranchTee_y: {\n", + " Generator_x: {'type': 'line', 'line': Line_1},\n", + " BranchTee_z: {'type': 'line', 'line': Line_2}}\n", + "```\n", + "\n", + "That means that Generator_x is connected to BranchTee_y by Line_1 and BranchTee_y is also connected to BranchTee_z by Line_2. Line_1 and Line_2 are [Line](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.components.Line) objects containig all important information about the line, such as length, equipment type, and geometry. Accessing this information can for example be done as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.3681789122707058" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "edge_dictionary = edisgo.network.mv_grid.graph.edge\n", + "# get random line\n", + "line = edge_dictionary.popitem()[1].popitem()[1]['line']\n", + "# get line length\n", + "line.length" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's have a look at all the **nodes**." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[GeneratorFluctuating_839361,\n", + " GeneratorFluctuating_839362,\n", + " GeneratorFluctuating_839363,\n", + " GeneratorFluctuating_839364,\n", + " GeneratorFluctuating_878450,\n", + " GeneratorFluctuating_878583,\n", + " GeneratorFluctuating_878609,\n", + " GeneratorFluctuating_878611,\n", + " GeneratorFluctuating_878614,\n", + " GeneratorFluctuating_878615]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get a list of all nodes (stations, generators, loads, branch tees)\n", + "# here, only the first 10 nodes are displayed\n", + "edisgo.network.mv_grid.graph.nodes()[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also filter for certain kinds of nodes, e.g. generators..." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[GeneratorFluctuating_839361,\n", + " GeneratorFluctuating_839362,\n", + " GeneratorFluctuating_839363,\n", + " GeneratorFluctuating_839364,\n", + " GeneratorFluctuating_878450,\n", + " GeneratorFluctuating_878583,\n", + " GeneratorFluctuating_878609,\n", + " GeneratorFluctuating_878611,\n", + " GeneratorFluctuating_878614,\n", + " GeneratorFluctuating_878615,\n", + " GeneratorFluctuating_878862,\n", + " GeneratorFluctuating_878863,\n", + " GeneratorFluctuating_878864,\n", + " GeneratorFluctuating_878865,\n", + " GeneratorFluctuating_878866,\n", + " GeneratorFluctuating_878867,\n", + " GeneratorFluctuating_878875,\n", + " GeneratorFluctuating_878950,\n", + " GeneratorFluctuating_878963]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get a list of all generators in the mv grid\n", + "edisgo.network.mv_grid.graph.nodes_by_attribute('generator')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... or get a list of all lv grids." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[LVGrid_122408,\n", + " LVGrid_485974,\n", + " LVGrid_138585,\n", + " LVGrid_119895,\n", + " LVGrid_119896,\n", + " LVGrid_119889,\n", + " LVGrid_119890,\n", + " LVGrid_119891,\n", + " LVGrid_119892,\n", + " LVGrid_119893]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get a list of all lv grids\n", + "# here, only the first 10 lv grids are displayed\n", + "list(edisgo.network.mv_grid.lv_grids)[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Future generator capacities \n", + "\n", + "In the open_eGo project we developed two future scenarios, the 'NEP 2035' and the 'ego 100' scenario. The 'NEP 2035' scenario closely follows the B2-Scenario 2035 from the German network developement plan (Netzentwicklungsplan NEP) 2015. The share of renewables is 65.8%, electricity demand is assumed to stay the same as in the status quo. The 'ego 100' scenario is based on the e-Highway 2050 scenario X-7 and assumes a share of renewables of 100% and again an equal electricity demand as in the status quo.\n", + "\n", + "As mentioned earlier, ding0 grids represent status quo networks and generator capacities. In order to analyse future scenarios the future generator park has to be imported." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:Right now only solar and wind generators can be imported from the oedb.\n" + ] + }, + { + "ename": "ProgrammingError", + "evalue": "(psycopg2.ProgrammingError) relation \"model_draft.ego_supply_res_powerplant_nep2035_mview\" does not exist\nLINE 2: FROM model_draft.ego_supply_res_powerplant_nep2035_mview \n ^\n [SQL: 'SELECT model_draft.ego_supply_res_powerplant_nep2035_mview.id, model_draft.ego_supply_res_powerplant_nep2035_mview.subst_id, model_draft.ego_supply_res_powerplant_nep2035_mview.la_id, model_draft.ego_supply_res_powerplant_nep2035_mview.mvlv_subst_id, model_draft.ego_supply_res_powerplant_nep2035_mview.electrical_capacity, model_draft.ego_supply_res_powerplant_nep2035_mview.generation_type, model_draft.ego_supply_res_powerplant_nep2035_mview.generation_subtype, model_draft.ego_supply_res_powerplant_nep2035_mview.voltage_level, ST_AsText(ST_Transform(model_draft.ego_supply_res_powerplant_nep2035_mview.rea_geom_new, %(ST_Transform_1)s)) AS geom, ST_AsText(ST_Transform(model_draft.ego_supply_res_powerplant_nep2035_mview.geom, %(ST_Transform_2)s)) AS geom_em \\nFROM model_draft.ego_supply_res_powerplant_nep2035_mview \\nWHERE model_draft.ego_supply_res_powerplant_nep2035_mview.subst_id = %(subst_id_1)s AND model_draft.ego_supply_res_powerplant_nep2035_mview.generation_type IN (%(generation_type_1)s, %(generation_type_2)s) AND model_draft.ego_supply_res_powerplant_nep2035_mview.voltage_level IN (%(voltage_level_1)s, %(voltage_level_2)s)'] [parameters: {'ST_Transform_1': 4326, 'ST_Transform_2': 4326, 'subst_id_1': 239, 'generation_type_1': 'solar', 'generation_type_2': 'wind', 'voltage_level_1': 4, 'voltage_level_2': 5}] (Background on this error at: http://sqlalche.me/e/f405)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mProgrammingError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/base.py\u001b[0m in \u001b[0;36m_execute_context\u001b[0;34m(self, dialect, constructor, statement, parameters, *args)\u001b[0m\n\u001b[1;32m 1192\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1193\u001b[0;31m context)\n\u001b[0m\u001b[1;32m 1194\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mBaseException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/default.py\u001b[0m in \u001b[0;36mdo_execute\u001b[0;34m(self, cursor, statement, parameters, context)\u001b[0m\n\u001b[1;32m 506\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdo_execute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcursor\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstatement\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 507\u001b[0;31m \u001b[0mcursor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstatement\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 508\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mProgrammingError\u001b[0m: relation \"model_draft.ego_supply_res_powerplant_nep2035_mview\" does not exist\nLINE 2: FROM model_draft.ego_supply_res_powerplant_nep2035_mview \n ^\n", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[0;31mProgrammingError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Import generators\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mscenario\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'nep2035'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0medisgo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mimport_generators\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgenerator_scenario\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mscenario\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/git_repos/eDisGo/edisgo/grid/network.py\u001b[0m in \u001b[0;36mimport_generators\u001b[0;34m(self, generator_scenario)\u001b[0m\n\u001b[1;32m 326\u001b[0m \u001b[0mdata_source\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'oedb'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 327\u001b[0m import_generators(network=self.network,\n\u001b[0;32m--> 328\u001b[0;31m data_source=data_source)\n\u001b[0m\u001b[1;32m 329\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 330\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0manalyze\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/git_repos/eDisGo/edisgo/data/import_data.py\u001b[0m in \u001b[0;36mimport_generators\u001b[0;34m(network, data_source, file)\u001b[0m\n\u001b[1;32m 984\u001b[0m logging.warning('Right now only solar and wind generators can be '\n\u001b[1;32m 985\u001b[0m 'imported from the oedb.')\n\u001b[0;32m--> 986\u001b[0;31m \u001b[0m_import_genos_from_oedb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnetwork\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mnetwork\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 987\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mdata_source\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'pypsa'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 988\u001b[0m \u001b[0m_import_genos_from_pypsa\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnetwork\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mnetwork\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfile\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfile\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/git_repos/eDisGo/edisgo/data/import_data.py\u001b[0m in \u001b[0;36m_import_genos_from_oedb\u001b[0;34m(network)\u001b[0m\n\u001b[1;32m 1844\u001b[0m \u001b[0;31m#generators_conv_mv = _import_conv_generators()\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1845\u001b[0m generators_res_mv, generators_res_lv = _import_res_generators(\n\u001b[0;32m-> 1846\u001b[0;31m types_condition)\n\u001b[0m\u001b[1;32m 1847\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1848\u001b[0m \u001b[0;31m#generators_mv = generators_conv_mv.append(generators_res_mv)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/git_repos/eDisGo/edisgo/data/import_data.py\u001b[0m in \u001b[0;36m_import_res_generators\u001b[0;34m(types_filter)\u001b[0m\n\u001b[1;32m 1089\u001b[0m generators_mv = pd.read_sql_query(generators_mv_sqla.statement,\n\u001b[1;32m 1090\u001b[0m \u001b[0msession\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbind\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1091\u001b[0;31m index_col='id')\n\u001b[0m\u001b[1;32m 1092\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1093\u001b[0m \u001b[0;31m# define generators with unknown subtype as 'unknown'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/pandas/io/sql.py\u001b[0m in \u001b[0;36mread_sql_query\u001b[0;34m(sql, con, index_col, coerce_float, params, parse_dates, chunksize)\u001b[0m\n\u001b[1;32m 330\u001b[0m return pandas_sql.read_query(\n\u001b[1;32m 331\u001b[0m \u001b[0msql\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindex_col\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mindex_col\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcoerce_float\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcoerce_float\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 332\u001b[0;31m parse_dates=parse_dates, chunksize=chunksize)\n\u001b[0m\u001b[1;32m 333\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 334\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/pandas/io/sql.py\u001b[0m in \u001b[0;36mread_query\u001b[0;34m(self, sql, index_col, coerce_float, parse_dates, params, chunksize)\u001b[0m\n\u001b[1;32m 1085\u001b[0m \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_convert_params\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msql\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1086\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1087\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1088\u001b[0m \u001b[0mcolumns\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1089\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/pandas/io/sql.py\u001b[0m in \u001b[0;36mexecute\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 976\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 977\u001b[0m \u001b[0;34m\"\"\"Simple passthrough to SQLAlchemy connectable\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 978\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconnectable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 979\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 980\u001b[0m def read_table(self, table_name, index_col=None, coerce_float=True,\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/base.py\u001b[0m in \u001b[0;36mexecute\u001b[0;34m(self, statement, *multiparams, **params)\u001b[0m\n\u001b[1;32m 2073\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2074\u001b[0m \u001b[0mconnection\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcontextual_connect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mclose_with_result\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2075\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mconnection\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstatement\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mmultiparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2076\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2077\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mscalar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstatement\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mmultiparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/base.py\u001b[0m in \u001b[0;36mexecute\u001b[0;34m(self, object, *multiparams, **params)\u001b[0m\n\u001b[1;32m 946\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mexc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mObjectNotExecutableError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 947\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 948\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mmeth\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmultiparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 949\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 950\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_execute_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmultiparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/sql/elements.py\u001b[0m in \u001b[0;36m_execute_on_connection\u001b[0;34m(self, connection, multiparams, params)\u001b[0m\n\u001b[1;32m 267\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_execute_on_connection\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconnection\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmultiparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 268\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msupports_execution\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 269\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mconnection\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_execute_clauseelement\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmultiparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 270\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 271\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mexc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mObjectNotExecutableError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/base.py\u001b[0m in \u001b[0;36m_execute_clauseelement\u001b[0;34m(self, elem, multiparams, params)\u001b[0m\n\u001b[1;32m 1058\u001b[0m \u001b[0mcompiled_sql\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1059\u001b[0m \u001b[0mdistilled_params\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1060\u001b[0;31m \u001b[0mcompiled_sql\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdistilled_params\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1061\u001b[0m )\n\u001b[1;32m 1062\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_has_events\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mengine\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_has_events\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/base.py\u001b[0m in \u001b[0;36m_execute_context\u001b[0;34m(self, dialect, constructor, statement, parameters, *args)\u001b[0m\n\u001b[1;32m 1198\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1199\u001b[0m \u001b[0mcursor\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1200\u001b[0;31m context)\n\u001b[0m\u001b[1;32m 1201\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1202\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_has_events\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mengine\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_has_events\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/base.py\u001b[0m in \u001b[0;36m_handle_dbapi_exception\u001b[0;34m(self, e, statement, parameters, cursor, context)\u001b[0m\n\u001b[1;32m 1411\u001b[0m util.raise_from_cause(\n\u001b[1;32m 1412\u001b[0m \u001b[0msqlalchemy_exception\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1413\u001b[0;31m \u001b[0mexc_info\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1414\u001b[0m )\n\u001b[1;32m 1415\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/util/compat.py\u001b[0m in \u001b[0;36mraise_from_cause\u001b[0;34m(exception, exc_info)\u001b[0m\n\u001b[1;32m 201\u001b[0m \u001b[0mexc_type\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mexc_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mexc_tb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mexc_info\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 202\u001b[0m \u001b[0mcause\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mexc_value\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mexc_value\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mexception\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 203\u001b[0;31m \u001b[0mreraise\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexception\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mexception\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtb\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mexc_tb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcause\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcause\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 204\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mpy3k\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/util/compat.py\u001b[0m in \u001b[0;36mreraise\u001b[0;34m(tp, value, tb, cause)\u001b[0m\n\u001b[1;32m 184\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__cause__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcause\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 185\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__traceback__\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mtb\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 186\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwith_traceback\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 187\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 188\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/base.py\u001b[0m in \u001b[0;36m_execute_context\u001b[0;34m(self, dialect, constructor, statement, parameters, *args)\u001b[0m\n\u001b[1;32m 1191\u001b[0m \u001b[0mstatement\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1192\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1193\u001b[0;31m context)\n\u001b[0m\u001b[1;32m 1194\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mBaseException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1195\u001b[0m self._handle_dbapi_exception(\n", + "\u001b[0;32m~/virtualenvs/open_ego_notebook/lib/python3.6/site-packages/sqlalchemy/engine/default.py\u001b[0m in \u001b[0;36mdo_execute\u001b[0;34m(self, cursor, statement, parameters, context)\u001b[0m\n\u001b[1;32m 505\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 506\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdo_execute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcursor\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstatement\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 507\u001b[0;31m \u001b[0mcursor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstatement\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 508\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 509\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdo_execute_no_params\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcursor\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstatement\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mProgrammingError\u001b[0m: (psycopg2.ProgrammingError) relation \"model_draft.ego_supply_res_powerplant_nep2035_mview\" does not exist\nLINE 2: FROM model_draft.ego_supply_res_powerplant_nep2035_mview \n ^\n [SQL: 'SELECT model_draft.ego_supply_res_powerplant_nep2035_mview.id, model_draft.ego_supply_res_powerplant_nep2035_mview.subst_id, model_draft.ego_supply_res_powerplant_nep2035_mview.la_id, model_draft.ego_supply_res_powerplant_nep2035_mview.mvlv_subst_id, model_draft.ego_supply_res_powerplant_nep2035_mview.electrical_capacity, model_draft.ego_supply_res_powerplant_nep2035_mview.generation_type, model_draft.ego_supply_res_powerplant_nep2035_mview.generation_subtype, model_draft.ego_supply_res_powerplant_nep2035_mview.voltage_level, ST_AsText(ST_Transform(model_draft.ego_supply_res_powerplant_nep2035_mview.rea_geom_new, %(ST_Transform_1)s)) AS geom, ST_AsText(ST_Transform(model_draft.ego_supply_res_powerplant_nep2035_mview.geom, %(ST_Transform_2)s)) AS geom_em \\nFROM model_draft.ego_supply_res_powerplant_nep2035_mview \\nWHERE model_draft.ego_supply_res_powerplant_nep2035_mview.subst_id = %(subst_id_1)s AND model_draft.ego_supply_res_powerplant_nep2035_mview.generation_type IN (%(generation_type_1)s, %(generation_type_2)s) AND model_draft.ego_supply_res_powerplant_nep2035_mview.voltage_level IN (%(voltage_level_1)s, %(voltage_level_2)s)'] [parameters: {'ST_Transform_1': 4326, 'ST_Transform_2': 4326, 'subst_id_1': 239, 'generation_type_1': 'solar', 'generation_type_2': 'wind', 'voltage_level_1': 4, 'voltage_level_2': 5}] (Background on this error at: http://sqlalche.me/e/f405)" + ] + } + ], + "source": [ + "# Import generators\n", + "scenario = 'nep2035'\n", + "edisgo.import_generators(generator_scenario=scenario)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can have a look at all generators again and compare it to the list of generators created earlier before the import of new generators." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "edisgo.network.mv_grid.graph.nodes_by_attribute('generator')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Grid reinforcement \n", + "\n", + "Now we can finally calculate grid expansion costs.\n", + "\n", + "The grid expansion methodology is based on the distribution grid study of dena [[1]](#[1]) and Baden-Wuerttemberg [[2]](#[2]). For now only a combined analysis of MV and LV grids is possible. The order grid expansion measures are conducted is as follows:\n", + "\n", + "* Reinforce transformers and lines due to over-loading issues\n", + "* Reinforce lines in MV grid due to over-voltage issues\n", + "* Reinforce lines in LV grid due to over-loading issues\n", + "* Reinforce transformers and lines due to over-loading issues\n", + "\n", + "Reinforcement of transformers and lines due to over-loading issues is performed twice, once in the beginning and again after fixing over-voltage problems, because the changed power flows after reinforcing the grid may lead to new over-loading issues. (For further explanation see the [documentation](http://edisgo.readthedocs.io/en/dev/features_in_detail.html#automatic-grid-expansion).)\n", + "\n", + "After each reinforcement step a non-linear power flow analyses is conducted using PyPSA. Let's do a power flow analysis before the reinforcement to see how many over-voltage issues there are." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:pypsa.pf:Slack bus for sub-network 0 is Bus_MVStation_239\n", + "INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network SubNetwork 0 for snapshots DatetimeIndex(['1970-01-01'], dtype='datetime64[ns]', freq='H')\n", + "INFO:pypsa.pf:Newton-Raphson solved in 3 iterations with error of 0.000001 in 0.519885 seconds\n" + ] + } + ], + "source": [ + "# Do non-linear power flow analysis with PyPSA\n", + "edisgo.analyze()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Voltage levels for ['GeneratorFluctuating_839361', 'GeneratorFluctuating_839362', 'GeneratorFluctuating_839363', 'GeneratorFluctuating_839364', 'GeneratorFluctuating_878450', 'GeneratorFluctuating_878583', 'GeneratorFluctuating_878609', 'GeneratorFluctuating_878611', 'GeneratorFluctuating_878614', 'GeneratorFluctuating_878615', 'GeneratorFluctuating_878862', 'GeneratorFluctuating_878863', 'GeneratorFluctuating_878864', 'GeneratorFluctuating_878865', 'GeneratorFluctuating_878866', 'GeneratorFluctuating_878867', 'GeneratorFluctuating_878875', 'GeneratorFluctuating_878950', 'GeneratorFluctuating_878963', 'BranchTee_MVGrid_239_1', 'BranchTee_MVGrid_239_2', 'BranchTee_MVGrid_239_3', 'BranchTee_MVGrid_239_4', 'BranchTee_MVGrid_239_5', 'BranchTee_MVGrid_239_6', 'BranchTee_MVGrid_239_7', 'BranchTee_MVGrid_239_8', 'BranchTee_MVGrid_239_9', 'BranchTee_MVGrid_239_10', 'BranchTee_MVGrid_239_11', 'BranchTee_MVGrid_239_12', 'BranchTee_MVGrid_239_13', 'BranchTee_MVGrid_239_14', 'BranchTee_MVGrid_239_15', 'BranchTee_MVGrid_239_16', 'BranchTee_MVGrid_239_17', 'BranchTee_MVGrid_239_18', 'BranchTee_MVGrid_239_19', 'BranchTee_MVGrid_239_20', 'BranchTee_MVGrid_239_21', 'BranchTee_MVGrid_239_22', 'BranchTee_MVGrid_239_23', 'BranchTee_MVGrid_239_24', 'BranchTee_MVGrid_239_25', 'BranchTee_MVGrid_239_26', 'BranchTee_MVGrid_239_27', 'BranchTee_MVGrid_239_28', 'BranchTee_MVGrid_239_29', 'BranchTee_MVGrid_239_30', 'BranchTee_MVGrid_239_31', 'BranchTee_MVGrid_239_32', 'BranchTee_MVGrid_239_33', 'BranchTee_MVGrid_239_34', 'BranchTee_MVGrid_239_35', 'BranchTee_MVGrid_239_36', 'BranchTee_MVGrid_239_37', 'BranchTee_MVGrid_239_38', 'BranchTee_MVGrid_239_39', 'BranchTee_MVGrid_239_40', 'BranchTee_MVGrid_239_41', 'BranchTee_MVGrid_239_42', 'BranchTee_MVGrid_239_43', 'BranchTee_MVGrid_239_44', 'BranchTee_MVGrid_239_45', 'BranchTee_MVGrid_239_46', 'BranchTee_MVGrid_239_47', 'BranchTee_MVGrid_239_48', 'BranchTee_MVGrid_239_49', 'BranchTee_MVGrid_239_50', 'BranchTee_MVGrid_239_51', 'BranchTee_MVGrid_239_52', 'BranchTee_MVGrid_239_53', 'BranchTee_MVGrid_239_54', 'BranchTee_MVGrid_239_55', 'BranchTee_MVGrid_239_56', 'BranchTee_MVGrid_239_57', 'BranchTee_MVGrid_239_58', 'BranchTee_MVGrid_239_59', 'BranchTee_MVGrid_239_60', 'BranchTee_MVGrid_239_61', 'BranchTee_MVGrid_239_62', 'BranchTee_MVGrid_239_63', 'BranchTee_MVGrid_239_64', 'BranchTee_MVGrid_239_65', 'BranchTee_MVGrid_239_66', 'BranchTee_MVGrid_239_67', 'BranchTee_MVGrid_239_68', 'BranchTee_MVGrid_239_69', 'BranchTee_MVGrid_239_70', 'BranchTee_MVGrid_239_71', 'BranchTee_MVGrid_239_72', 'BranchTee_MVGrid_239_73', 'BranchTee_MVGrid_239_74', 'BranchTee_MVGrid_239_75', 'BranchTee_MVGrid_239_76', 'BranchTee_MVGrid_239_77', 'BranchTee_MVGrid_239_78', 'BranchTee_MVGrid_239_79', 'BranchTee_MVGrid_239_80', 'BranchTee_MVGrid_239_81', 'BranchTee_MVGrid_239_82', 'BranchTee_MVGrid_239_83', 'BranchTee_MVGrid_239_84', 'BranchTee_MVGrid_239_85', 'BranchTee_MVGrid_239_86', 'BranchTee_MVGrid_239_87', 'BranchTee_MVGrid_239_88', 'BranchTee_MVGrid_239_89', 'BranchTee_MVGrid_239_90', 'BranchTee_MVGrid_239_91', 'BranchTee_MVGrid_239_92', 'BranchTee_MVGrid_239_93', 'BranchTee_MVGrid_239_94', 'LVStation_122408', 'LVStation_485974', 'LVStation_138585', 'LVStation_119895', 'LVStation_119896', 'LVStation_119889', 'LVStation_119890', 'LVStation_119891', 'LVStation_119892', 'LVStation_119893', 'LVStation_119894', 'LVStation_119897', 'LVStation_119898', 'LVStation_119899', 'LVStation_119900', 'LVStation_119901', 'LVStation_417530', 'LVStation_419885', 'LVStation_121940', 'LVStation_121941', 'LVStation_122426', 'LVStation_122480', 'LVStation_418254', 'LVStation_419605', 'LVStation_416441', 'LVStation_418546', 'LVStation_416244', 'LVStation_417898', 'LVStation_419795', 'LVStation_120737', 'LVStation_120736', 'LVStation_120738', 'LVStation_120942', 'LVStation_120943', 'LVStation_122230', 'LVStation_122231', 'LVStation_418237', 'LVStation_416449', 'LVStation_417550', 'LVStation_139107', 'LVStation_120585', 'LVStation_417276', 'LVStation_122520', 'LVStation_419726', 'LVStation_121776', 'LVStation_419327', 'LVStation_417734', 'LVStation_125015', 'LVStation_125016', 'LVStation_125017', 'LVStation_500931', 'LVStation_418244', 'LVStation_120411', 'LVStation_121317', 'LVStation_121318', 'LVStation_416815', 'LVStation_139104', 'LVStation_139105', 'LVStation_139106', 'LVStation_139192', 'LVStation_119903', 'LVStation_119904', 'LVStation_418449', 'LVStation_419079', 'LVStation_119697', 'LVStation_119698', 'LVStation_122076', 'LVStation_122077', 'LVStation_122078', 'LVStation_122124', 'LVStation_122125', 'LVStation_122122', 'LVStation_122123', 'LVStation_124543', 'LVStation_124911', 'LVStation_124910', 'LVStation_139183', 'LVStation_139184', 'LVStation_139185', 'LVStation_139186', 'LVStation_139187', 'LVStation_139188', 'LVStation_139189', 'LVStation_488816', 'LVStation_490252', 'LVStation_490253', 'LVStation_118322', 'LVStation_118323', 'LVStation_118324', 'LVStation_515314', 'LVStation_120387', 'LVStation_120388', 'LVStation_120389', 'LVStation_120390', 'LVStation_120853', 'LVStation_511325', 'LVStation_120470', 'LVStation_417987', 'LVStation_119612', 'LVStation_119613', 'LVStation_119701', 'LVStation_119702', 'LVStation_119703', 'LVStation_119704', 'LVStation_120038', 'LVStation_120555', 'LVStation_500916', 'LVStation_418547', 'LVStation_121286', 'LVStation_121287', 'LVStation_121288', 'LVStation_121289', 'LVStation_121741', 'LVStation_121742', 'LVStation_121743', 'LVStation_496409', 'LVStation_416983', 'LVStation_121878', 'LVStation_121879', 'LVStation_121880', 'LVStation_496410', 'LVStation_121915', 'LVStation_121916', 'LVStation_121917', 'LVStation_121918', 'LVStation_121919', 'LVStation_416589', 'LVStation_122400', 'LVStation_122401', 'LVStation_122696', 'LVStation_122697', 'LVStation_122698', 'LVStation_122699', 'LVStation_123655', 'LVStation_124010', 'LVStation_124011', 'LVStation_124109', 'LVStation_124110', 'LVStation_124111', 'LVStation_417936', 'LVStation_124902', 'LVStation_416175', 'LVStation_125210', 'LVStation_125211', 'LVStation_125212', 'LVStation_125213', 'LVStation_125214', 'LVStation_125215', 'LVStation_125216', 'LVStation_125217', 'LVStation_503036', 'LVStation_125269', 'LVStation_125267', 'LVStation_125268', 'LVStation_120898', 'LVStation_120899', 'LVStation_139149', 'LVStation_139150', 'LVStation_139151', 'LVStation_139152', 'LVStation_417909', 'LVStation_124085', 'LVStation_124086', 'LVStation_124581', 'LVStation_124582', 'LVStation_124583', 'LVStation_124584', 'LVStation_498758', 'MVStation_239', 'MVDisconnectingPoint_1', 'MVDisconnectingPoint_2', 'MVDisconnectingPoint_3', 'MVDisconnectingPoint_4', 'MVDisconnectingPoint_5'] are not returned from PFA\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
1970-01-01
\n", + "
" + ], + "text/plain": [ + "Empty DataFrame\n", + "Columns: []\n", + "Index: [1970-01-01 00:00:00]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get voltage at each node from power-flow analysis results\n", + "v_mag_pu_pfa = edisgo.network.results.v_res(nodes=edisgo.network.mv_grid.graph.nodes())\n", + "# set maximum allowed voltage deviation to 10%\n", + "max_v_dev = 0.1\n", + "# find all nodes with a node voltage deviation greater the allowed voltage deviation\n", + "v_mag_pu_pfa[(v_mag_pu_pfa > (1 + max_v_dev))] - 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Reinforcement is invoked doing the following:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Do grid reinforcement\n", + "edisgo.reinforce()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's check for over-voltage issues again:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# get voltage at each node from power-flow analysis results\n", + "v_mag_pu_pfa = edisgo.network.results.v_res(nodes=edisgo.network.mv_grid.graph.nodes())\n", + "# set maximum allowed voltage deviation to 10%\n", + "max_v_dev = 0.1\n", + "# find all nodes with a node voltage deviation greater the allowed voltage deviation\n", + "v_mag_pu_pfa[(v_mag_pu_pfa > (1 + max_v_dev))] - 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Evaluate results \n", + "\n", + "Above we already saw how to access voltage results from the power flow analysis. All results are stored in the [Results](http://edisgo.readthedocs.io/en/dev/api/edisgo.grid.html#edisgo.grid.network.Results) object and can be accessed through\n", + "```python\n", + "edisgo.network.results\n", + "```\n", + "\n", + "All changes in the grid conducted during the grid reinforcement, such as removed and new lines and new transformers, can be viewed as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "edisgo.network.results.equipment_changes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also retrieve grid expansion costs through:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "costs = edisgo.network.results.grid_expansion_costs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are interested in accumulated costs you could group them like that:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# group costs by type\n", + "costs_grouped = costs.groupby(['type']).sum()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An overview of the assumptions used to calculate grid expansion costs can be found in the [documentation]( http://edisgo.readthedocs.io/en/dev/features_in_detail.html#grid-expansion-costs)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's compare the grid expansion costs for the 'NEP 2035' scenario with grid expansion costs for the 'ego 100' scenario. Therefore, we first have to setup the new scenario and calculate grid expansion costs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# initialize new EDisGo object with 'ego 100' scenario\n", + "edisgo_ego100 = EDisGo(ding0_grid=ding0_grid,\n", + " worst_case_analysis=worst_case_analysis,\n", + " generator_scenario='ego100')\n", + "# conduct grid reinforcement\n", + "edisgo_ego100.reinforce()\n", + "# get grouped costs\n", + "costs_grouped_ego100 = edisgo_ego100.network.results.grid_expansion_costs.groupby(['type']).sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## References \n", + "\n", + " [1] A.C. Agricola et al.: dena-Verteilnetzstudie: Ausbau- und Innovationsbedarf der Stromverteilnetze in Deutschland bis 2030. 2012.\n", + "\n", + " [2] C. Rehtanz et al.: Verteilnetzstudie für das Land Baden-Württemberg, ef.Ruhr GmbH, 2017." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/ego/examples/tutorials/grid_1476.png b/ego/examples/tutorials/grid_1476.png new file mode 100644 index 0000000000000000000000000000000000000000..cbef8115e5939a78c4c5d3b8c821a7236c74dfc9 GIT binary patch literal 410425 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

Q>j6WqQ!5-ZL1yE2d7He+^@Ls|vh3CXj`S z$R9s)=<3ZE0DuSwY0)+MK!Gp-(E4q>qrL0yryRsr>ErN~l3Wc^p>*tb4gG`~ql$rG zvThRLV9+*FlviF#DWzl>8FM!H3IMmAYEAC6VaPA#w`O4=CIaFy-nzG^%d0Of|HVh| zd;W7LhP`ppWTSBAwb#!-zIN)NYfCFVP-+Y<0pwFP)J$%^4=~wx_(CYZch$e2%~q?t zXGVgxENT~T4c-g82X6&!%3@@ry<)*TK-fW0p1@92tv~d>@B1G<@YAPG96NGo^_ge> z?17U=#F0^%cNJkqg%HN-vbSUNtN@0niik-{g@{qRU31Zz&E)#6;ZTTR)uRvlFFpHd zX;*s+~j9jy|w@EmuhSGqpK4}641tw;!GpRbs5($Pj^C`En1tXmvlY7SK{0gmr_E-;nsf=70}YRJjGWSll` zyMtPP|J99Y4sjW%kd;+C5 zb!!131ThbGlC^7%t()_o{mA{-FOB&UO3~TJZa?yMR~~xf)ucJD%lpDhVWu3cv@8oB zP>N8^5^2Le3nlW^to~}Bg_u<4-sTK3OSunkMHCzu)f8_>?4IU=S(9x{8F zus`z?Kl&X%@WcQ8_ndp<>yLoc>s3);m4%+Gz_MC`t`>wKohK%$tz<&*LWnZYrBuXh zlqkybrcVLjXt(kBiUHUr3a&J3o3`88&p(+3Jvu5}%XLTcgJ+7*d@;E&6I)}+CB`*+ zpcb3pg4-CW!<~*5+gZ8V*aH(ILUc!O1r1STq69JFmJ#YUyeb2Nj6zw6IALZXMF>G6 z6T>e0i8$L~g%2`@&kF%tg0~ta2W zL&}<4Zekrm;7mImMpU#8YI8Zh%0g1`^_jifHh&G{4t{IMuT|GKM(aI|x7WAlmJ=D< zycosyfT`n$eLv_&uY3K0Uwv;++o`U7-fs3bT2;B{bgiD)dE#9!Jp86t;${f|i0B>Hcoq}Q z_HJ@Gpq`OxauJPrU*i=Gs4RW!Prtb5sWWt3%SY3lg1`2B3gE5}+Q&MDXaMX#*hFLIIZ?ZTdk{iYEF25N7vPpb z+g5W!-(w;Xm`s34lOFGbFuUj{mj#$;3LW;`HndIwfDd^6roM8`ynNOE(I;B~AcbR9 zR}yQg%VfDRdCu18P&L|N9ivI=4TMd6RiQGo$UZjbS!vwGTRi~QAS@!X(7;@m3cPcv z+?uDQrftOz=FD*o78pPPFa#)!jRTb~M~R{VstI~fC}0i@Ax)Jwj(~zBW+A0irU+yO zmCo%0`kGo?-x)Lnph9J0LIqGN5cliV3d7~t-1jV10Yk?3PX_5c7HE=S{wEW7^ylOUrk25xldt!*qPJoyVPJU2 zFq&IUYB#CX2+q;wj@|CbP^Ss>vJ%&{>@x@-I-ZWPIIR@C?&19F-jMEu;R`pvZhNh{ zakJgqOz!c(6OvDy-FnNro_XYn>l5*t9Qz4Opjg#tk#i{Im_N`=*0bT!X#c}zKdW@# ziM(UMF!g5%zG9}d7~Qz~JgPX)hgmk@!;6h88{<1yAVF2#w-``JZG(5<3Pc1Huee)M z>cz&M1vrzhiXi|n!dh^u93vWo~zI^nQ+g03C zC_`T4`HQa}|L(u@PoI41QxBhOAfOTw09~G%I4LSB1Iy_Nu^#!dNGVQ1<%03_noGi##&F&HEW=LCP)Smj zMeyFaN}DL{Z;`LkZEuoxAms_ydh+N(VCIn@_VK1r$6b~+7FMckRH20g0N{c6Xj%;} zsat9SsT*71@yo2Mt8)XF>WX=8% z!gqPW0AR>Ye#PF$bGzVYj~mg^fx_meZFg}(m(b5 zv(H`ow%!n&gD0PgpL{9?*h4}@gl4DgEM#*_!?~5bJD+tHv+h#bo*&FDRRCU$+ZW?l z*($IW@a&RiD4w?#m;)@4L_-)DzJ`vG-)_W<{jSe3TfFaMaD2h=?BKo60dGY3rjo;vCm=LW~W<&#R+0;;j%Gx%}Qpng);#5il4 z=*Fd0rKR!JyfqCDjb>K`^}yNJwwj$@rNrTG2mz$zK;Wy| zf1_?vD}WdT3aoD*6yt|Yec)7;RWmfKP4hw`C<(!r2#7*N6J?W*{t63O8TSUf-p1v7 zZ+1s7LKaF%sGyAO?VGPC@n&Q6*>evZSW1TBkQz}ahDzI6a1e!*LdLBn#N7piGQ0b_ z@5C75{QG}<>(TT3L-xJLNBdvQA?%hKrSRzx%zQc&WvJ0M`qItD`t{4*c6$BR{1e~yUFTP%X1&07A>ZfS!&myFp+#A5i;2np6HlFyQ5U^xsm>=4i$dQE(uX=T4VOf)DV;XX0sWU5eFK z2`l5SzT}GW`)O6qN70>D6^B}OSW$cO@MWSXYQdyzBb$_icV}g`p zSBLt#E5ojGmArYSvvGal8PZkcKZd*BKXpEN@ zlf$pE9V)Y_rB3}HmpRv@?|P2_AQT7BL;w<;V=x>%Fr!d4b(AMOCjcnIsCHLyj+K&O z+^|DRDWyu7a)5|IkoQ@Z8EZoz8z-SE5Lqh2RQF`fQK5~4EJ(^mxl1c~;_zRUb->-mdbk{`wmzVV)$Z6ITPq(E$wNvR zWfva%+MTW2!5n?|*=Nq5-|t0V+od+DIXOxJtl@n8%LRZRgM4_7Z&Hg@I~?Ti(6m+_U~%Vbu^ZM@bJ0( z;dA*v_&)fLy(h=(cPV_4D;-Z52lp!F0l?T4V=~ygTC9aS0;XNS#2^ke>|Le|C}#>p z9sp~RRnl6lZ@+!s*ppqwvu#`fV6n4!tG{Q3BIC&S1^^JC{6hI^2a>mTUkCSuzwKT- z0XeY_Scn&4v^IS|7Uq%TkNm&s|NU6^q@B<|Jd2!*EKjSdifw0UJ_f{hJaOh7Pu%~T zzw?Fn{peqO`Pmzr+v)H9oAS=tRRH&$ zm^1Fo$?}Cu_L&!>?|9evqe#&0AOS#VY;==|fi?$lw3$SWVdYwSfA*RPx>|(=j64Et5;uGy7bJ78`vygRFS;{hC*%bbaCJ+2h#v4 zff0p7Wno4SB828qge0@75Y4%|Sc-^6I%qE}j|M$r&a+f%i()4-D@EW&qm^ePtxcW{ zBV)-|+C&UMM3TrCnT{KE^60C)H>@yZTU&Z?Wcig_{@KbT8%A2ulmV>> zIRKDw;lw<|W=P)oLeKcU*Hduz)J1!fR-R1tj*OL5wE#>iS%OP%mq4C^Nkd>%1Ofmn z7veaMqu4tklvPS00x^Eix4+@snU(i^|G$z_eDqTqfi=o7cA8$CY1(lz2n z3ax`Ef=@A*P4Uv z_|Em4QgC$Dojh8dI$r&~|K@rPMuiX}Yere&jF)~qTWWF(Op2B~Y4J2xxPYt$BICI& z1prI6Yj8duCW3v_UK%b&B5DGF)D{>*fd*m?(p3cjN&!*Q@Xl!y5s`_KJRP8Li2cEk zq9{TDL>59;-b*1vAQXT?ppZIBq&CUiYH;Pw)*6EtRE;>M$ne@`8J)A+C9yP0i{MK@ z5nSon06-N|GFg*OtlHtVe5d}kU*cDx25cg|cM?iquH`dIEAV4zcwE6VwysJ^CaxU% zQZzfMq$VH$2*gHgi_#&2o!DiV_+aOzzm!og4l?fdd98z!x&=eob9}FUS?tS^P;<6) z{>b5@FFp6vspE$#QeN&gVJQpj_2l{2?Emw9Uv~GB(E0m|=U=wZUHnhhr8Pvv#JiY) zz`&?{6#_$Ws4X)I1Y#5dBh*B$j!*=6?D&aBGl@m;RjN$V_oIH*OTp*Wh}Z)KkXlF) zJjsa>1~Fp@LdY5u@YzVWy8AV+LUJ}l+YnL&7Q&T;N=QL@icvE5!BW!8Ag&dBI1*OY zOCd&1HO(SJ`*>Fj`>Fodij8N(ttkvAnqaK}CCSSC>NTM8mgS)sV-tJ;B?pu*%q(7r z7$nR(d`Eky!BojBKt!xZl#fZoQeIep)>>JyLX;s8u@_Pa*$N>IVFbLy9Ebu#%{Riw z9$ER&zx}~~{_~&sgO5J*;!C$q9_@bTGuKxU!jF8P`_X?IKJ{69;g4YwIMQkuDhGP^ zc!{85VIV+_lcE5C#~#Z6?SJgPbj7BbY$W46q0F;KQFDS!8m|6~CG`sr#x zk4(4GCM+KvEFT>#9~rD19h^NjdhbIg)viaS27ulmP4n`|%DfaJN1lP;iN_?<8e16O z9rX%N;utBaZL5NFQmg$ljRA>i*5!l<5y3PL{(KqYsSYYQb8RT}}l_d-a9h`~$rb%AcSDKfiiEcW$Y z0`sKqhk#sWgi-{@Qp+eNp~$<-`PxdeGjr`UGY`|EnOH<5@5CK>$zRq86L0%1y4IBQ z5;O%aH_K=-5;KdW{js&B;wKg#1b}`z>UO$NTZOwEk}ibZ)lFDmW37e#3X$<176JF4 zDgof)6+2t-{c1*2L-~1eE#wj3+sP=sDTKV2p){LFz@f zcB9%tQ6~xlrs&>`{1i>ZRRMOK*`YnKZ7q(QD%UTRflw=gVxBTseZ_eStBSX_31XZV zfB;h69^Ra7TDgygrF2|mJG1z}5k2=@xV^iD5W`NU+H;Ho+pz$oqLhKCv1|3XnQbnZ zdr>ST9!%!|0JV2*$~%Wxx8kakeIP=qDYzb^Gm&Mk5Q(@Hs2_j4`^@t<`h)WC z|G*QEJ$(4zr`0=u?~8|j=ogTc`S8DknT)JqT6Cn5-oD+K7zcMWr(T$egrT0cXHRYb z93p~eUW~r>vGJU2$M(iR?A(f#wFP&n5$u*htHMY{I4~x@X@w&{-b|-sd40m#pCJfiP6I9 z_VUpTF-#-f5=1kBb#l^_JhC#M7gZb?%69`g2ah!}!vFv#9^V~PE?tbKZfa7$3q*G; zm+!*a3=XXhIBerWr`alsDw1vC0x%EzLv3`PrE#NOW@+4Pjru*Ew2UzXFWz1YhgMdM zwMr>uuChUUeu<0RHX2M^qqA%yrhq7p9OmBk4sf_}JBP;-V`RG#l`Mx@A*Gbk3MoWy;t|YXT2^|3dF%QID-M=PB zzUNhB8tqhWvma|(d_WV`M)Yi?XGWu4nL+I*z#M$Y&Hm6?|IRR0&{MM4&V2T6j!-jk zola4pX0ziQ3Mqqg9Gp#B%tYR!*2bt3wF@xFO6fF%RBG{4pSkpFzx~+sZb@o)a# z+~>X=f94B~jqULXS(vZh_jfP;;NMjH&hi^yXD>YEAARh62w}v(dG2qpNQ}#Ktz+NM zu-%zncd^%ur|vJQl>~q^FXPDMRX#o8jB+wN5dh>Q$EopF6cVaHOgxqUR~2fzf2N_R zyS3wlc+1S>oIp8*;nVQtj&HTG-HGOej%*ZHRT)Kbg%~%QD5Upcapllx(5tEnt-J5^ zeQ^{G`a4O|XfzwHs>&iKf^>632ozG;I4QG~F#vAey1jnl$eC8toI0kj-l~osZZHr~ zDJA+U2NY;*6ekS9o4&1x3f^p&Xw{VDudJYqtRapqWIK^LbI(zmk3~003BX8vtw-C8eo+Y8D!IdJNn(wko9{ zRLxe$`=FF$*AvQ){i2A%ty}UnUjYyR0IBRgdi->pKU37A&F3ygcZ;ocokvJr+pv$d z^9U=^Qi}cY(#Z#DBVQGAw#;IYTU6?q|q5JGt8o_+p>#RrZT z;5F&4v!DIKs~`R3rAHq+{44+4_o0;k?f1R*fB%(_|HS|F&Bd>NviQF~5&i7yg-VpVCV};P+f2mXF}Jq2x0jX{DFjq< zdvil8C4{8lgcM4l)&p%T!kdT`MT_0dc@y`tlCNCX=Z?31#ie_S5%VK*+OJCDlY3-$jkyoAT>QYB0^)ql@x*$$U+HUVsoy(M*!-6Su6$C z7GE43D%}g|oIHSQWwfF=PP5$k{fWzHG;+>GQ544qE}mM)626=ACpZTAMti*uCs@_4as(_O9ILZkKke%=EGx{5Pn001BWNklssEwd(nQU6a^*((PyW&EfA%j|+f91&>(e*BE_>r+ z*<8mL)v$>3ZfIQ3xbPvGL`)+3hd=TY@B6#o`{}><(&t`%?v3w$^WF=BVbDV~>>OJu zbp$h26X)^(u@G34esQklsw|TXQ(H0`dj$kvmj}mrU7b1rV8kk&TpDI(z*!r!`b|V6 z7r>0yCF6}j)HBToe;>`A;KqxJZ-$$U!%nvaz`_{7A9th53`tyGD$I;zrb19#wKwQKVUF8(bM& zSyrizhE;JoCGAMMG8LjSDn17HU8HBGhY%nzpif5}Tz$c~%rI(T)Tk{HIPL%gPsELZ z0!tIBiiH{*eK^161_#Dg08q*(U_aw7^5GAE_(LE1(89ukQmQD5jg5`>zyJN`&+jkv ze>Gzv>K==i3)(gf0RYHea^>&n&2<2cKyts=TiTT)h+56q^!n-Y;#{XQH+0bJ51O&& z?QOMi0HMsg!bGjwcIeI)Om~j6r^>Yrb@3I;6eze5DyghgwvMMJZu{zBde(yOLv z$yiA>TgxhWPh#7WwBtlMFE5@u_3lsq`5*r9KThV_4G1Xf7Jm_h%AP&<))S{6-)z#+Q|kbL?YQ}_ zM~5Xoa(?Bp55D(LpISYA`s~K5ube&IuFCxQk;dBAV19mSADKoPv~BUucVvI~+RH+~ z%Azl`?TP9E`+la9u+S)8UQdR{xM|<@&fzz_ZKU@Cqr^_I0f3_kUd!aM$%Oss|Mi#O z``*9xnupI{e&woOeZ0}#>&eI4J5(skzM0KkU;pmQWCWC)W^BwEAR z%MD;=MKWcBC?SQQ@q(;&FaVgXWsRNK$kb)7-JULiK;RK*oPtJ-ssu7bK$TPZVAy-| z^PhUt*Swt=ymwVu+BilOx;@W)WovU&NkP@1)$W?OvA*_&b~|dcjBQn;otVQZ-Hf7G z1i}!4l2VyAiCC$=kVVpd(N&S>7El5JD1`IF)kWUkyibXCAn%G{)Mz0cc6 zj=I=NW&TY6Q!2QS-``Qog8^RTM}lLqz>M)J(fq zUq?l{9nY8!Kl|*nzw}GLG<_LD_`nA~@H0R2GyDE99Ax&i@6F2jEH7=`9rQNa-9-RU zTzuu&T22tFxY-2=D@*gEd`wpgc|V>z5&GAvUY}N0?o6rGfo8OKZ!&oHRQahV8!x;p z0YK{LP8Sk&7he)7^*3}Mn?-UZ2vb$%Sb|AV78o@aO!t-T3%~I5AN%?@oyyZR^S2i8 zbns;};1C0sd4Pz$2PV`OlqK(wDAWmEk%6)`-pW-;MTRy8S2BZWE?~W!tC1rb=MD%w zRe7V-!8t%t`w1`u)tHeFv^~Ubf@0TIb3o<2#k^(Sj~aUxzpJW!HS}PTK@+231_sZQ z)R<`3RRCb%XJTvA@x7O)LUjt1hGJI5W(4_(2i4}*TIH&R2%Qj~%eCI6&Rm;9uC$^M zxsejmaP7nIH;h_;>Ed&Tj`x}^TxRlf z)=1g)MSg1G;;;YfKlsu2JqjFJ5w0^Y%yq}}X9gDWIjKkjz@gH}Wsvz(>vikiMhhG{OA<0Aj5Q?}+fXe&-KXmKVSA>tA1QupBQi9jr>PZH$E5 z17~>x07$cU2ch=w<`V25qVY3eoJgv%zht8A(Of9y)Y*I2a%cdqpGl=GFf zph5Mwj{wD`D-cjB?W&R}EG#akX?g@3jF=UJQ5a#|tO1c-yw!P7IPTx<12NYHVd8Pl z?!8BC#>h1@GjElHdy@C}3}g1hJ}ISA2jqVtgdhL$AD^|eV&)4MF6{X#t&-RlrOQf^ zc?k>vg%cdm%x21W=&}GaQnKo^SpW#_W_A%$>I3g~MN@07H47mCkb>7bI`cr8%D-S{1i`?4(E}EVi%LgI z;ISq9^cR2s2j2Z{*+8J~2i^%jVj{E_q&j}2vAua!$wvUCmaZ(hktFq%o`%l)<-TBt zxJ&TxGnFN^)Y7Z1^75v9_;fA9oKC9xpOQtu-~$Dami($O~bHgTD7(2nC254JcNi0tF#e2tr6?Dgj6+ zIX-YADJ6)BUvq6lSNDGdtnGkNU_q_|Z}tYUlAYr~zy)WsCCcN+kALukA54-&DOFWf zzu$lNyWhS4J_9hueDH%GoNa|2LU`|c-+Sklk=08J9VV*R*^E$#Slz=LI})_*<${P5 zG5|Cial1XPL~2)5yRlr)-(LVgAh>eP)M}P}Blz-ev9$`t ztJPqWhwEjpeurEpL{xXRgdzo#blMFc+!J5-=1+b4&%ghBziUuks<&)m3_|!x6M;QN z*xrYQhN#AB;`#Nfj~?$JsZp-b;!l27%s zt&uP+9Y{}D7RImjLN2ovdE(sJ*EEvW(;F8n35Wt3EkF=bG6f1E5Lp`$5iwVevOJ@1 z3<#Q4E5w4aq1!UnfwMS{Id}jRQr7}b=U7T*jdiXfL?I+U343Q2>AhK{I$O00bgHu@7(E?JF_GTbWxB?r*jtC2x(=t)jS^Zpoy* zfZ~yb=80pcnGO4;+*LN3^Um8CDF|0?XK6-JFiJ&Hl%*r9H2@>xu(ypuxUvisgw(-1 z6k=|E@!4meU0GfM4n>|rtx%pVjlxAjNfhb^n2+-*_ zO!MqTe$IP=`V4UfbcLl3RRviMqz5ikU|Kd zk|vLKX0=T9U!lNyk5WoRG>BZJ5&|#@fii9&2Wbo{BW+aw6*?tJjuRg#5i!?H;a)5> zWnx$EhnAM(h22AtQW%2*XOBy8nEpGTv1%Wc8%GR0*oq$QByU+=dDzlIlV7N=eqnU& z$>GMIuHX91_V5O;+;TuD`h%U}uqWmC*NWIU&(4KOr5l|qYoAsj%(%OO5Q3rM^c+g2 z;Hp9@MZx*tg_IP$k`kpyuoMC_LkNNy>MsNk2xa9x9!ui!vt-Y_LXdXyB|$ zXT}t0uGxI+2q{pY zl(J6Sl~SmbLaxtz{a4SF*FK+Jy6A3SE!GE6cnITLK*|zA&imz;*4k#X`Iiz{$6wf( z^OFc3sx`n}*6jg^!;%T>dD5C>I@>!t07s^uQtUnr!Wn&Zt5CHeI6 z@`X$GZn0HJ6WqZ$otD;?K3Efx?#9gyCtq?`xXeYJT{3I5y^vyGB&@RhXXqk@8Q}aKmiE>pngOb-VMt^C%G42_|Dp(@-&50i3pXYY(zGh<~4w7x*KHl<0RESVX6g&J8{1dyN*u=2&y!V&DbY;gAp;Q=NE>E!*c|7w6j~QWCA3071c;L)&r)faf>TBl1wbSsB_&G5 zM8q`6s`>dd(<7zeXSKh+AOO_K%rZInBHaeWh#+b#HH6sdZ*^h-#Q1^L(S>V`E4N{( z1pum6=mkf?dzVM1UHGl%UitFx|KZ1f{--~1YgDBH8**Z=%8ZEfanmd9sgewpt1==H z6G_3u1SGr%3(R4Z7VJlX=30qX6Cp_&3K9YUyz@XDrcL1Y*0Ly6pd$dVIPQp5PmJIL z2pOspq@L!jC+*SW3r7Lq!p75Eeza)Bna14nJ6rt#sLXWg1|K+(t3)MWu5-A|Dp&N{ zbBos6G)hc@ac^tg7+aM^)SC0&X&XyzT%HN308j`_`@Q4Gj}L~! zsH&1?%lkkfltm$+06&n)$TfV6Ck;yOQfHCMBy%fF)EIHz?Lheq0Zi8ZW2e{P1G%bx z-0s0!h4kK`5@Xys>^9(H=84U&N5uLhl=o;(@Ru}DNau28lEBXC+hMkvdgs;}f|OCt zl%NLyyB7ntjfRd629ULB>~qd1!v0Y1^yTKJ>!*#a9ktV!I|I4hliNMH(^pq-7y!6> zm)Hsb-j{cC+JEcZBazxgyIu+FgDR^Zam-w>yO`f>nxqNg*y_rQFT5mhbF-rk$9*lU zMw(R?SVm)R9Uvf3QH?RI8u1ab=C_UwjVq7LQtMEaQk%dm5gv+$+N)1qp<0{t;npk77^tb2&nC!$FJDxHYp8t`&{XjSLMa2vBVKwu+P-J4TMqm^@k znS?aKc|fQWt5&nyU)x-6oe(UvF~F3EA(NB79cfKWN(v%MT`r{(qOEKuL)cKYd8kOA>SOGvPt8D{?Jdyx_FJZUsyM1tVbm3Zg zvriPrmsK%R+6t+aNtB7JVtDzv!7u#Eum0js{v-e#YMSf)w9y&Y2I|;qCC{s+8`)Kb zEQK*PDr>uLtk*7*f@2U;YSUWs0jB9T0Dv5)x4{RYRb7Ar9w%`#Jc04TPD>?7%;K#= zial}t7CRkzWV2Yq31~GAE>d%z)k+uu@WIy}oqz(o6LFKu z9Fzea1pq(@%!82ci>(XZ+@xxn?Q&HLA$=ee<1U+l0)+t6o|nV`kQGBP_cFeLiRNee zayeNJ8!v;>(?dXCt~8Ra5(}+30Nx%9cB=Bma0EKyF)xx)37)~}##Pq|br-@Iu@#sG z-(=|RW(~n3;`PgyPaR8&!bR~SGsQ_URJtq+^s=kw%PfQV|EKM}<0ZSUGSRhm zI`x8En#k;m6>4z~jLH&!pioJd%0LH%wXE z`c)ZD-FUjHpqdRfMpOz8Kw}MB`6Bl(6sKOec<}IU*lc$O0G;>GURwLL-}>YCz3<1E z?3aGpA-5e3H3_g8TM=Q(kGq+49C^lt=VgNy1j-SK+*E^@aam{+2CCQTNq<|=ACLut zAyx=Lo6A@kZpL^5L%bCUuEkr81t!LkeG;^~cC}t@Mv9JgT80S#B2b~SZg|kKoNkGQfwM+TrVz0LzXiJ__d6se^3D5yrSN2Jf1I)4< zoaIso;8O?uK{Ala55f?+Nb*(}S`9w|kU&KeoR|6j^Sr+!j3xxPDEmn<++A7iY$-q? zohka*&qQX75tip@i3p4VF-#O35g>Qt{MItz7jhhL9Rae&8raNX(OS|4F#ZyHCjXML zrUd}3ch}mzwF@g}FJIX>v~S1a%H@oF{2dBAym=PR0j@W=mXbhcPO`@)s8x6aM) zX7x*a!!jB+y$}$Q@B%yN@F28BfzA*z&N=xZ5HLR^B2{{jF9Rz)eeYX)H;Jxsf` z>i&zAuMB#plGLDJ2#z=p)aV+AWvG!)z2H{s@-IjTf&pU5+a;b!JL4EHMX&_pRn1pV zUpe5q>15qHDvAObvnF!{oS`oABg0b05VnIY0E8fr2rWM5)vZUmXK*@ z3=j#+^<=50tAHe#e@@!|5-wfFwg`+o0zzonkZ?4g*HkG0_I<5eKfS)mBJP|7b7-R$-x?Ko8@M>513*!oEW9_ z^+=Fq$Zs{q1Dc+k9}Id+IV0)eX1pd-pb$g#6SAB$t1aUm0AyJ|j^jMf85h!zoHf$( zvosM>g_Q+AJm1}DGY9|~icG}M$YTn!dgGO`Duf~3VQ1mvIr56enq@DFNv}^iG&$KCEOmGVt zon^u!l#Gj#-|DPGr-|V>zttMe(UmJ+xnlzYau$(nn(#2PNuP%i5$9pWImh^mMvs5V z;AZua=O2wLw%0bhXAZvp&K+oZo_4)(+vf8|v6ax5Xg2YZYOOxf=;OdCi~%4}*j^?U zCx7&@9c5shYTC($Y1XsJ36#}-8m+|jEUIQNuKA*TAn<8zx0CDF7gA zJ0?KI!++(%yN2PoHJCR@bIYULKyL8TrKSFrr{40qJyMFz*`~E~02GC?KS+%BckQY@ zarBdS?Emg!qjEqlJf|;=Ht%S4snBcljC;OwqTB@|ATTKHf63@FRFyrijIoYQQYwNm z+VG5;p!7Ufs$}XRW3I@{vxF4js47F$wkj(X9#oiL6_K>ib$QFA#uQWjOJD;80LJDH zjiEsSy?dr-krWz%h4lS{K=k?Ela>odjC1C6!G+lBDFg&-2sX(*VpD&peA*F6cwh=A zl$6qHCCJrzrDEJvFj)cRS85MFb>X%nGpA4Cl{J1~FCY*BD%1{gVt%0q{e+!88YHv9Uw{?NIj=U;Q1tnezp2IIuJSJK5FeU^UYCw}XT&ptd+ zYuDnN?|aP=Z;bdIG3L?9P^E(=up-L1>KL!9lR7jBTCfQ5Uja0?5M6SpvGoApjVP`*yh^<^iDY@!XQfkv0jik>E8k(KhQkHWukC*=JF1608i)im)Y2~(iOsC4Bs&9Qq$-dOjVgvl?t(jOsYoh8G$mQ1 zR;Pl8jha&aGH*Gz#ladTwNg0inA28UrhEbdU99Vi^RO}JScYHP^gZ< zkP$I9ZnVilj!YD3(l=ItZnxF|hKwtz{K5|az+^o+HSMeRZMPWspTHRW-3QN9B3lN{ z%Vy&Xy_3US31B{I)-k{_Gi_6(;{wm)sk>iiWTi02?IypH5*Nv>`TgZuNBL|vwEXz50sDl_6h4TOaI6%2PBZSQFQ8s+m zm>^vclcNg(L~w3MQv(13WQ^RVLpYaFuNMS+CUo44f~LQb?mWM-S_Xa zEc<~UdrusB?QRjM*a0t!OvqNFvHL&%;CG!mb#k6AUjP6g07*naRPq;p{deE++Jmot z{lQcvPD*J}N#0NR{{4r~olYQK;hYy3A!}JTV@+Y5O9uUJxBKwt&%N#KZ$Er!QQ@^n znb_VIJYL-@`HUmEZe1j`v2Jk!@^9bc)^vX*4~>hag8m@+g5MMI4h zEVm9rPeK54TjUU<(-H#at;7c5CXvntl+TCJ+{El!o}caY&*gML)feMx995TFtum@^ z>hU9t+%OmeCV??Z6BI&6vM6#Pq;u9;!x_s9Eu<10SzOK1c4NwSJ;o60%}J|uzu!X~ z){dmdGpni8=tk0Fqfu0Y14X);f8q;&zi{`0DyAhL>UHrUEtDWQ)3itCSO!4aXv6#r z+9y^XP6T`7!kv!jk@e@bGh`gGGB$A_pnL$x0R|QKT!Yjv1j4HD|a7W(P~<5v6!R^^Q1j~*bQQx1<2z96WU_xbL2R=@{zcww+N%n(=rXE|gw0!kD03 zx5oxD;A*T2Ja&Ujkr%z; z$4}S`kA23O-p~BlTLy^_=sob+j~BfQ6F1NN=_jA~z+ZpX zLviTVx%=+fd(Yv$>no>!?*o7Pi~r?KB8bRYvcivYt3gXJ{Z-VgY6c7DaSb27W+)UDp|CTr$=OqwaV`0}8v%WVQRkEa;qPLvpr@K8= zVaeROm@cmuZDUM|={7AsQ;anFsK`Nul=guu5Hf{65g}t?T(w3cDoRs8mSq_i5^<{6 zKMr=H$hvX0mZT}?oC}_(sgTV2Sr^U%fObwh=h9?R2BrvI1RIUj>|&nUXT)Myi30#= z_ma@BA%c+H@(Y*qeGAG+Rv_ia*PndF^x-w#dcJ+`?x~vsuCy~?3CD0AQ~@yojN_<$ zZ8XU3AmKPki3m1dlGPwM{1aO3{}l!S03{YlG8~_!_;Prw)y`qRH}ri$Xd6Vdfaqy_QK`UNA>{#O~|Wj zgKni+iCF;v)3Vlf0|Y=`uDuAGO7Fvd7@ap{Ef#@iXgOI*Jo)8Gi92G>RVFLO+R#`1BzKOknGu$=X;BwK0>Bcj zI$M++XY~B?P%#!J7#FEoHwo>l`ziDL)*W46&AA8YfJ+7dn|d`lb2+4-fYOu)Lw;y^ zouwEq=NyCrGN3#V3IGTo2*Yk`T__)&6`tqFp`|d43S$|fHC7;FocB5#O8MH@Fp7lq zoV96cuFxRgw62wT)^M5&k0k8cw_~H79Dj1z@`joQl-yWnos*2Abs(}8vpPu=9+E)3 zZDOA@=3r(2$@P;DT>MAN1VCBeXN1E>HFCtp96iul5OSpOJDjxO5QnrGUgopqG8*izmCCRD{mzZHC+A zOrARDlXKZ%BW^6hrW#hBcD!JidCknsKK}e?k|sK!7=+h1fzQ=Y#0)`jfy`M80Jq(| zTS&-Y5Y)(uQH`*pyo=4RxaA6!-Yq$&NW@mgq z005rV0~p)pZy%;eM}o>X91|>b)|H#YO-&F2vP16z0W@8HcK@aAMaWQSwst4%GX<;Ae6;#7$| zQ*6UAv@?6+PYDYvcA95NpK1*Sr$B2&3E3lr?{9MZ*9~U1L>%@+Np%f z1->f`XG@nY?G+OMP?h1uY}sY}=E)=8#_4BQPWeG>1arA{a&vMzKx1K(?n>DJgBZrH z5fOG32!ZjLMyHl=NxbDzY!*2^D+;g3jI!&HYdl_ z`-=>tVMd@NhfJJIug)K-z{7KAk5B4?FUj^_ZagBSL@tpmasgau03zxNH#_zzc+HZ6 zsPjHD&X^!)x%8vSIB(lvLizEwC^jzO(rna=L@B^n_{$gb_3mxG_L(=_Q!r$Xs6+{j zwTO83GXAF@`R!*u>OFjVOK)feL@ z?2yf)#gz>jEWnG#Rt9))xK}A4UJx%F448A)NGwz!CnF}P0wyCAsZb#xfJj^Y&LHUr z{>y4gz6=>U@@nNIB=FFD?O9ChC`-KT!yKqMHm7w}1ccAN$Yme(L!Z zh6w>KrLYlm$g6L>rAL@wzH+5en}|Hck^SKJf9D7P^v{3exBu`*fB3uW(gJ|VNe`Ux zaouzu`t<*}X})ohVY>&dK0kcRS554j20hFdbm8jq{NddUkw5c7-tF}#n~k6rC!N;+ z@!p^L;rIUND{ntEj_+HeN6@V&V(029TZv(DA_^7hQEWwoMlhA&@KXqBwlXtFi_llO zHlC72+8uS%mZNV5ky5A59>3-A9nP9Sx|q9=3+YtN2>?iwZfkYTi&Qn9mYY`Uy&h-0 zTYB~kxg6HA%}fmt968Rp(S{4=0NAF&X-Pd`f>~=tTr>R++XT}yJ3z+$FeCs#M$Q&R zfkQiHq4P{KE}0YzL>T2o?)!cz7OL~S*IR=MIOo7?#dXlu`Hll562oOKS;Om}+e8c*V?M&@yJSKC(?nmf8WSuvSaqA-2mMFnS^59ugi z3gB|2OY4MW$f&ISl^kKtj5b_|Au*inrmh$vLkGZ>as=gtBf~ENZ%xzm*6qsFM6_ea zjvF3qiBb~5c75d0xZW=df*=M;0U+jP&B!F#>b7LYjr*Mh73MF6dv93=0HfKZ)Ae2Z zuK*u1F3GtuxhO2I!33Ohw2iR2C85nF05A!{FSkzHA`ai=U6p;Jp{Os4Fi(@DZD!`@ zdcAdk4Mz@1X^m0R^?E&oj7bHEGqaVMAbVylut zOtM|{uW@Efik4%U3Z%B_Al>kTn&eey1Z8okCWd!<^JXIl-M4DU?JX0q7;0PC{f_~?hf`?YVJt<1sp zMlVw&<7F`q8wp;{bl(?otVA*`oL*fzbj$+YQ$YUEkc z?X`CqW+2FNkqO>5y~G*-h%2?(`8{cpJ%2KO?o@o@jGrXz?QiH&OrwUnAu|*ix~)fP z$iLPW#a3@p$)PveAVXse>CC1Agha+y*z$~CR8Ck2K#ogQ4PzoQMWF=e78wu$>-RcV zXdZzpG#J5!GA7X;?lR9W_nY9DA z&v?>-wE&<8jcDQE7ng%W^=>7$7n3Xd;<;D_$_oJ?&j(;RCWMMvaKOay60j7+!jkPf z;r6i|&S!(@_Mi2zYj~~D0j|UGPyy3x9%A8KT zeZfC1wx(&9Y%xTRh&rj!#a1m0t?NL(Jh+f@y_$7YzHt80Ji^M_SA{5y8CqiK;#%>1mJmUxz#?hUwzLH|ImN`Z{I-{4U>UFQf$YZI(u>Hz;(Ja zMUe(C(hLRwld5_qUFoY0sf2bt$BNwaE0w0rY>^_f@wB%C0HCB}zQ_*VYTByoaoOY& z0CLkA-=bbWlwTQ#L;%2oJDo0dC|NVzf(%1;8=KkX4Jo%hmxX=>23;;ynVACTF6|9< zW+jI(W(b4~2v}Tq&aLWBq;`$UjHM&awl9(AEZ9OblQds$EeBy?q+gPaO21`5V94fn zO^K*xtv&JhsheN99{`-mjm|*uezGd0u-01T<&G+qT4`lg4p+GEc-y!A?g#(i5B~VC z|Ks=kTL4&FZ++p(hv%9dlC^f?0IX0RBHpsMcje+qRZR5;`O?agPM*5!RSf`Wck=m# z;gb2MAA4}u{M=o9*XnW)j?_w>it-x0us)9AGUVJ;3clt;Ohl{N8!-SUy^2InQw{*A zWSsGE(gOe@a^!MKoPo4ID6re^^}^Z&w+z6|OfSq#&wY07N{$xM5fOSKX9xhFeLVbz z@7{Cjyf>~>`0%55{Pg=z8_#UMtTMzP)>9>$% zHGqWFa-WkBOpNhc39se1IxD2G;Ipzz(DO$;ag!$^tXPK36ePUi0bfqM6##&!BAf-r z!I87p7UQ|dbzSOSy>+FnBq}M2Zq5{c?70J{&QH{nQ#H=`J$E%e_>psry?&UKX$=5O8(?_y%;lR8&m$R~<|LGbkaD|Y zE;@PnAD`;4&(H6ko}5V2?78QkG{vej1Ev;Ub-)vDYBIrz9OIeqC7&q`;UgKe4nc+kA@K)hy6;=rEEFOCATb@mGMNUyBq zoekH|Yykjdv?V}tL=L$Gqe+F#0|x*E&KlrY{zd?>q&o+I9LnKM--Zd$Qup!+w-yw> zBvim75j9+WdR89o^y{PzCA~{;JG=E8~Yg(GLl-En+|!8e*WQ~{KexXT*qsL^dj$m&!a!WQvIel{{U7*9QRwge_ODMKI3ru#+;I;LAL}|P zr{!waF4YDi2sLYEwnYRxBkC4Zl@5^wEZ-mPe!hPK5hXciyxg`1-2_3m2Lqp1oynC7 z&)UJo2*7RtgV(@9C9W!@8qp`@CH3rzGKmnJ-j;7MupvY1Azyu&<63>_ya>_E79OAbK zClSFKgNT60h0Yx0rVE}=)-J8~E)`FdZSjHc?+IpmE^UfR-?cYq1cDwY*0qGq$fAsj ztX0LGdC)Da;hs=aLEdjBSF$wA*39!~dmBzHa{Dye4K3JbR-OTqL%Dc!1v&$=1|=E- zG=v;Ced?&3t4x$UD{D7}>#QkN8XPhxG7!o-yBTx90wR!g_REL27G|q{HLdiy0pFn# za!#ml{Bgc65+H=lNLxxQnVNXuf%5GNC8iVQQunBYr${vdi?;^s%FQ zdI~y4uU&Na9IQWc^zzLIr^?>#QoA9~^5>3Uyyfr$R{>W6B4!R^frPkke@;ii|6aEu@T?_0OH@-+KEuR;$%t`h}nR`v))8YL$Au z)~Hn*^=h+GZ%))3^=hMDt5#yXVZX!ZVmag+?&#HLAIYA0>^M~Z{hG$s>xVNM zwu2;1Srx=4RArJ^Je17Z2Yb(gD+m}Pu|UvU!(`a}F7TZq3O4T+(0BmJ3zNZeo2387Cl@^pPA0#iewF z6st4c6HF=qAOz+Naalr#zKA=$wvrxqP_UD6^(JKKGf(jRKY#yM{^t81di3bC|KY87 z5OPM8=b7N8ojnO5t#cD~J~PP)naKu>vn&}Hij)j=dhF+a<*}(|^9R589YxyZ6H#=z z(=j+L!I5Q~72uvY`N`LySmS~Afl3FIXklm052?E-fDHvvp2l;sifyw$G>W?y7{2l zv)HQEY5?%v|ND;5JQ_XvsRKvuJwJ}OaxWmOk;`$sRfMq_^m$ad9&hEGo7|1?)-}0O z3KSS?WT0)a^JCN5G3HT0 zTqG8Ah!u4E48$OjGO#WO05A5%eqlFYX1(wTQIovoOSw%U#1Ycq0+G-oTpR;seT785}j5D+25`D)jn-I&^!)+gJ|xxwUo=f2%Xu69qZ!zwsO zmRsZ?JqHXpTIheSw(jCr0HhQXEP!JEH&2Nx}46i{S= zSt#XH$@k@EMVCdMTq;?ta~e|+SNAN=rN6?s?d97X)iZ@%-J zzv-QwZm-quw%VOmySu*8K6U0otJ7(>yPaNde9c6}I1U^2TD?|l)GE!1`ou)tIP+fb z7irNxc=hi;-28)53fdHjddck7xodyI`=TQNp!2@uu{Aj$j~w=xDi?Va(rOJ{lz1xu zkTEESaGoh`7s{B6NR|j-seMkcy&D=QB*#t0ATlAC5dAHYFeC(k^B2!Ne`EV&uzM=t3iU^+-SXT+6Dd&Ky#YYsSUqKW{rUTq>G=JVxFp#XQy0lIBAdXK>DfEj3v_zxD(cIVxX!3ep4^1Fg~X3GmJDdK>`WQoU1fS){|6 z{f=*Jedf{V_!D!zwqL1dFj5M37OWdW3L_;pON4BMw}LUq#0YN%w$+SJn_5u-ppB8r z=ZtZV6k)g5iyb}n%;yi@dY99g9(0{^)>`SI@K|0Xo~r<4F05eUXmbq&?>aHhHBlBFCGm}6Jj-{CQF4M4x6Bvj2Br?dJ#hj z09+`>Bq%Jp4zF>6-mXP&$nWWmSVmK#ii`5fQfGJ!5$Qb528cKq;GR99PRWltgC02z z+_NYxV2^WKU;$iND_jN&yjawwBc9b_RvVb~{eSYYe|+Te*SzYkU;D2=2>{)0FG~mY z#v~%vYt?$Kx@Xto%l;U>{-BJ)?RIy))xL1)>T_34(mO2xWR3Ll^76qwdjLTB)f?(D zj)wHMtO-q#5;-mu0F{-%5<{F+wZ83ap>^aKLWxWvqD3a;m|vEVWHd5S{zjbhmdS6O zfGa6!HyCf91Ay4Cag%JN6$m^vm1e~;M2B2(lk|BImFW^gMu(=_m(}SswOa2 za%mmsTnKBeQmV&X&-So~yS(PafkUZ1f#RfdH$lZKtcq@&|nV5;znyVs#G$D0mhP=G8md%Ynvt6MwSj3X9Ll_V706Ymv0okj;sj) zu%H1pjaSJGb)CsMC0P_$OG0qRSjli2Wwnek=QME1H#G^r^4`IYd42JU{Ng7Mf8{ql zHLhF%OakIK-fBw&=2A`ufIuQcYpKLrkt~#8CBR6zf(!ma_lbk{h*NqwB;<=rWJBG&`$qmkNj zXCQOv3YHtxPLg&7=iD#CkfNMrj5E?XD4#KA0a)t1c2tRKf$~W~YTAHbE)Lc>TM5Ax z4u(9k@nfzz=bDXd=`zGDUC7j7u%;;srV*91Wo^!_+m%E9%`R~OK$ZZ(T8Eq3;KQ+r z<#pUPsaj;5xiJd_85l~ostSB)2ICyzc0C(JPGjv5vy*#cXQqQX=L`sLxoP3(@vFBS zo+D@D+D5Mvf8e7}eBeW0c-378?|b#WtlRg3f=L1yXbk`y$T!AHA&7`0a@4xWg@_-1 zj@T-*Xxv@t*T#IJr{f8i_D zYYyJMXLM~=XV*|8U}V8S4gm7BBV+)GrRK=>W182_+0GDmvlbY0wuGU8h|mvBGCc*IWc*s6w>aDI0mx)uW<( zE9=0T%{K&#!#8~Tvq#_Zoo^x_vTnq=C2K6>fS|R0#ykxKv5gPZ4+4O3bC;9nYV;WC zlg`#b!rAjD-}CNQzyAYI{?AW5`;BkDJz`*OQI?Xq5T57dS%T=|y6(3kAuCTGJM-W_ zT==OU{f1{RuB~0kcFZq$BGiK(+$Ab~fUDYTN&pxXvgR`(6acP5@1~pX%Ui1~BOu@|cjL>!mvPK_=3=gP zc-wNvm#MtSvUkvetni|5Fc7R5%6trKc>=phms?JfhM0~vf}?dX(i150djyx6>wFov z$MS3PwK6kh0)-ciW31O4xnp7XxiinqPB3Gv5d5ugy7kw8_n}|-@qfc5f8o@|M?d!T zpZxjbt82Z_K6>)rSMD)XVa0&Jb4(bcl^UXiRMvZuueP!e{ly~>Japk*-}d(Z@+0pa zR}2{qCFQ@oxlRi4^Y{F?&NGhN!gNWD(D?ung$jYljznycaVEI*Z!BK3IhwMnoQ%Mm z^%?=H3J=!v*0JJBxrbt08aKvobq<99z|qdbO8#W;)LpgkDn+x#RHf=?A~@E2_wP05br9h~M+=ul}7sdh}y|^Yr0Ei--4309a>Dk>@>~_yL7sKTqQ` z7xdM&_QyW{#IODQ+pL3@0IWb$zl9_5bl_D1fN^o@#5oxTI~sF-SqnvEsN3CCN)7^$ zVWEqPoC;j1U5eUES8V0LbmR@?$Ff`pp3i7t62m>g7%S1wuZdsbZ948~(xarFF=mC@ zq@$L#Zy08p2&yptChu@Wx&7uhcYgi%r@F1+sZSrc`>UTHsR99%#wctHZxzBwuY|43 z`$JyH$e1MMLFAAzKEzuQarkWJnuk%}^a{_`ygH}ka(ZQ7Jj)qF#{96l0F}1wBS300 z&PgfWvVATX0I0B{x$vdx6~K`7N!NI|nzaEy2C-YcYB@b8u0$cPv&zZ*(&VJqEs|!u z1>dEzSTFhpY=^kFa4POD-MZHT=!8g7h6S%(Lf`njg35T zViGGCa|;4ShKp;(@`RXPwO2=&jwuS@(&_>kC+EOf(m4w%DOhcCDYmH@y~L-N@1|k~ zz?|JiBGbiS6l$j?C!Tp$pmSH32hQ1J$FF?gL!W!<=!Jc|rw$(qzxFF{d;44O{?K23 z(GO=%Urb+dq>fPQ7q%p6m04K3tB;-zNv}Ngna}n6*}LEI%6sp=^Hr~Ule$r0g;Mb^ zY5CzxwMhLF2V;x+!R9y37y&6j3Zv74t~u({rcgl@N494VoV&TpaD4=;;lqf z_-iiR3s zh|btlC~O0F(x6zEq}X z039$KRjxT;&!tO6`?6kd%sB3BrTxTx31v-t@ZONB_Ut zLmxkM*Bg(+CfZrOdX?PQ%5;5Lf^ppcuVT#l&OW z6vet+Wh$ECai%lpoRASXOJo7iSwq@b=L#(D-Me!&#b?hir?uQuasWw$J^{2{*0O2O zW#DY0*R7BY!L4sVR3pwu{8ne(d3(ZyNF{w94FV?vKyGAR4CRLGCBw^?JlKuM?=@jM zc3TztpB7s+PDpc}8MM*C`odsva-ADXwlrK!d4F$kc&)co+Kvh#979NZ5L6HuFis$t zA2{cD7_BF(v(+th(vjt3-JRCz@i;H`WEH4tPRLTU-vclgi~)`URwIpW0xwCov8M9%+;LJoHImr`a-d|=T$Gf z@Z9&mOHMU|SlUOQ>b^`9)QfwA|FcH!iZ!#oNVABn44OplI!^Dl;fzMWm!uQmcwhy9 zs$XM<5fMioqc1$Mj&`eZZ4Gih#9P@=+U|VOxu1196g6;bVk@!8KFyZyDdmc2Jz2;i*LiU;X&DK=&F-0&E)#>?RNJgAAjz@|K6w8Tgfl~<|ppCbH3S_xarVzFFCnIou zvw{grief3ZZiP{FNAQ&&{+U<;F#cmxOLMUM?UPN(##sN z;=1SmTi(+C^S`aFT&n%auipQy@A-@u(5BWUBb~EN?ZMKf*J?Htiy%Nmlk`NT=B#4? zwkVhoV9dNfIWL=M(yMJ@%5xLbYP)n&Om(Tf+-XmEyyzD;iW8l3@VX*D43%eSa3!VO zcAfMsYw(KF{T>Jj;Bu2CLeKC35UiC#t68^yU~-}z|0yH1dNqxESw9-`wY>O z5&))Set$H7;^Nv$&X%b)Ke6*{cDWDPz~#=mz)~%oV1OZdc_mHJx;znK>>P2)opV+p zFxpJ#CF-1nhtAUIR)0D9t>Q+HUdZgl{GStB5e)!njX*T1%yO&K-dKUjp&iXI>B}~1 zQNtAk+##aX#s_9d5}_R>N~Jxjvm4YK?|kK4jSFHazcT(($iV81OFwH_zfp5mBOjr$ zvdDTPMdaqh;uoHLFlY6NM))f~`?g>DnYUFUiO7n=lQOq1T9{UU^{G$p+O_Ldul%No zIRE6MkEF@-dv;c=b%<`Nk$&vY-~X1c-Z9yXkTFe|t8sxuih`Q|-m&K8WnXi~hHH8)=D04Qk#-k3TJ^Iog=)%`|k?a&*nf3i3=G%O$l zKq?9n5;pw>j5Y@0LjPRgABngdIi~w6avKBk{4(<@5?!0C7mkLq@I>U?$Ycy1649~8 zj(^X4|HBZa72cM|t+VCU$7q9nBt`&0u_H4~wdDLwr#IBvK&)IkfA{S(h|uliExr7v z*R2hD#=B`B(B8Z6-1AotJbm+_>9@Z5CM2POHACl%b?3Z}ai%DwtN{Qa+t7Sf_;tOJ zDV5eH){MMxWo5eJbDKsoM#k8tddS)Hmmc`LhyHB;pM^)11^CNP|F5sO^$tdJfv*67 z6+|v~Mv^ta1UVw3du*$w@5lkTa@r6uXAD!Dy+&ob;Fgv?Wjc*L2>^cB82zTV-<1B) zyVl~|QV2giz)DH$GSlNYJIY}%egV9aB-aKxk(r9old z?{kpZ$W$RB39L@rH}4(I{&}asltnhgw(d{^{~;^ZN^zu zt2?J|1Aq(Ni>J*}dEyAm>(RB4>ovja8kE4Af=iz(grQQ&*2*w$AG^^h9(wq>U-`M4 zt=*_pCbBFa&NdeUULmS)bWEDLsmTdn5qSQ6ufFf8V-rsud-(R7Yl!S`AAI)ySMNEn zyW*Vd57On8-sH@!%C9h{!(nvRFM1cLyF~qzikSJY z2=?q$lll5K%SCeTMLu?P#LHyO*Mlu}Ss8ieM1D2OVSt;BJ&X}KKrDZwk=*?t8|idVx1gkP*RZDSFRS9PaTtwe(~%pZf=l3g+7sv;*BDkVBEX?miZ$G zr{43EA9}-A9GIGptRu+@fSl3b{0l32>MyjcmsyGh9p0%n9$SxR>OoU3wK`A!{U3(2 z_qDs-qQADjeCg`)1_0WW_8-}KsNWXK9O-X^kE+0XTB2{NXhYwe;P1uaOxu!W!=i`Js2Mcl-R0KH7Nx@%aZnc=tDa z*W;sqa;D(QE8ox>i<|*NBm`%elw1m16kJM2FpjsnLUZAd&gygbRJ=3?MlkHVjQZ_^ zQkel?t!yeU--@%TSdWJdQS5&h%3;rN!W?g9$cN`{$4fn!s;mz zR~@;W3bbI*DCQE&Lq05PbIzco+yWpM!@|0=M|RJ3lmDN#HxIMyy6QvM+QXUeP;+&4 zSI>i5k~K@#U?EwSkpbKB2ex^EM;JnY*d`<%2w<>-jj;&{cJdw&KOQ*1dk_*P+t?U` z4Yn+K(qN65pr)Hfeq zn7MIx>UTxEGvSQ@xzG!3md7GQNGl`&4+5h!>H-UewS=%jZ8IWb90|F!vBJE%@PBer z)@2qlYd0;-m+`HwZVLdE?yt!+Cy#YI9XvYC{r+^RT-ZW-F@UJc+7&KjZGCxdeL0wH z&_JTLzuy#mE$wYNgf7!d`AC<dMo!KJQXukg(wP@Zb*7k3D7R zTSe6)1mH5b#y0jcZ@3&nuo<<+xU4x@_^zrC5D{#`U{#KltUVO(<%rRxS^5#nNfj{< zJP^Jw%cwP!*5`s7Yk8&jj=&f@^}^hqBeVUZIAV<1yZ|8)&^gCFuYwb~)Zw7a0}QOQ z5sS_jXIIUNGFtAAOmudTjy7o6Y9?-t)#^`HjE+_^-bekhKk4 zS?)b`yc^dh_U*pzwR?6+US9H`LgHX1YhGACaPZ*4^|jT%`rKph{Fgtpb9Acg713zK zBm%(hrzamd`S|YI%oiT}=CRqiTkf4adHUkS$ViO*+U9jHr6<7i3rC#us!>ICjg_tn z5g`IuYe_TD?_XmDtudPMzCb;{6!6F{Q8A`pc>7Yf$N%iF>tFul(TSP%ov(Wl0DyoY z3^7=ob5jzBem_1YJ)@1_tnceL=&%_JlB)AX^(k!)W9))iAj>%C!VmL2TXSbJDMKlG zS?>k!+*;WIR61%fQ;*u-IQasF2qlZ9Qq~lxg|R>$_ts6X5$?kvOxC+o;Y6I~hqUlr zeO>F7P=?%9Qq@|UoQ0sv!3@W~q&Kp9?7ixmnMYq*aI@xqe-{9NgQB&{ghz~!W1q`w zt?;C?9G&j~A?vWHMgWX4lPeK=OpI|pzim$7BOm$5($doAnY?S)u6MrkomXE+|5!`- zMx^{QzO~T^0iaa<+V0__Hv_=qo#Oz|FLnX|!irhAHoAFP%~yXYikuupRvq$r0XUzg zj`xxOrQmtl3H^GtDI}uJ;U`o%)=g(sZIDIim2D>?ze*8QFFC8Z@IU^E|FPcgeEg#y zc;u^}5<)PrMNtsBN(hHB=4=#%?Wu{{#ktehTyr=IsoOQRny7o6P47DPt%;|eIe*{X zhnAN*t={f??*6X8-&AU2{3;E*yr5Q{y!7ME{N15BtF+3E%FpxiJhoGlds5EI@q_-3 zwbUX5U6nN~N*W6l8gDsmwrk~3q4^8!!h zoo*|GBu*p&fb`;<$8Q{diE-uf!eYs}f`J@g|Ns8KXTEvrru%QGejy~-{G#y4>VCW* z0OSBk|B<0cJ(E6Nm9`Plap~_e$ImQGg-o!B0hgB7Y!oJ$^q|`*rYGxf{oXr&^YEc&X4bW{CBO>x`|dkTXnb5EB~B_*cv4eJQjr&-3h*0OL6T zV4O)O3yUEq0ALIwp`9%O1XMlP`%M?EHKi~7yLXN}yNc~YBIk}o71)}tAuw>sbs>;Z z7zCI!$Y|0EqNF0Np|c?RL%k*ZkW&8Yul}kKn|;eR0m@JR^iRL(O>f%r$KAVkU;fUQ zwU_a&a~Dqm+*p(d0AXC4zpzf_6U$=_4ublWG(tkhZ6j&o5&}4`Qt6Gg7h3h1(M3fJ z-N87Lp8xFXs&m#En+2IKLdNB$mA@fSLYMK5swcX$#AUEqdX{nTUGM$SowwimgFo>7 zB_B0xM|bV?_-F(&D$COIJ!3QgDJA^CtJR7|v|5%50BSXnrWi-;d{@Qwu`ho93-A5u z`@i}$Jn-s!E*}BLMAfBko0qt(%4Qnw1a%!0gWCi>JrE)_kLh2rw@8b0NAJa+SqVTbK1$-FfhlufFi;Q%g#Z ze8)Y9u7v!hqA!G6&Ar=izW%0b_s!CPgK!iasykvlW@JItWU?M^QvW8UYj6((>JScMrVw65| zZZ~bkoarllSgVF|8Nd9_#cs+z{de`h{GHo{ggYNP1_0y?mANYm7RIj35rG8>4eAUsWH!)xY==Lov~ME=+?cTFigw9B zi2l8?KnQ5a^|Z;gYjD*yjUH?)Ne|3!Q;$k62|2Krf~@1|pyv0RVur)tx2) z#)TKvbgxBFc1P2*7vQd=2Lz$cQ>%(|rZ?{mCc|JK3}!HOxdbN2Xws!~#s~$2ZcJPB z1s{6op<~C6-F)-S+fIz3J^0{*SAWB|Z&&lJ>+RmI={f+EB?18F!mm%+WyL)K0744b zJg|cJ0hw+pE0H>%}w|<=?2W!-o97JVTmmPr1l*V9?C~(fGqMMM|%bF3x zItGon?)kNcvtuor4&ST?NCQNaE+=HTT}NW0s4l$~puQ|T=ZILTzUxv;?hvuxgu)g; zoLSAl0TY~Y(q`jR5{dU$L%#vUpgDqc+G+?U$G&y4B_t8ESeEhbt>Gt94PKl@n z0MZWuKuC}BF7keQK}bQm6jA~JA0CBCkp0;rk~#py6i;NMtTSe;^Aaw7^d$2{VsWj_ zPp_dz0PCvRHVq=xbVV$jB}#1EcKNDKJ%|nmqX)g|Z)Lip9RM)KY}&E5}8l>>Xn0H9EV>bwUYPmDGI zV6>?!apZ^`Eu^!yqC1n4>IfWR6H1o@^;c{_Z)rne8M8Tl(G zmS*MnA-?1G@X)=r>nebubME+KCl23qfUMD-b(eM=FyI~}qs|gJvc>}A18Tf=+Bxf} z-?+e4Fx%>6c89^5WA%yA{deE9`;I&J-g$TZ_PhS-ba!R7m)V{YzDet@$b&k6%>y%^ z`rFUUmB%}9T5Wnx^v8TH17ASI825%+aMsZ|v6Q=5 z!T10GmjNPU+>?IHm>iZUhX_h*%G2)DTYvUb&GF1y{DWV+Z*^^Q1K&#EtaFaYQ6+V1 zv_Zx#asU{v&EcV|PjM$E^p5c)+%eM z$79jdF26D2#Wn7S4x#0WQ>JxFbn=7)KsX_uUcInFJ+C?1Fk&<{8bFYe{~(*IN2)#BC*^Q)mh1%tR103=euBSaW-UZGmU2MfA+0!c=f$^-OQL8J{}nN#>RK7Ei%p^cK}3HWd?w(F$@E6qxJfQ z`|r%2KmNy0cB4nXaqKTX`8TIdFa6!4$@jkT_GWY9DnlXtn4HV_aBMGW4w?lRM-fBi7ivJ<7^&Fk4dD68?y}JoX$K7v7ctzZywhRz3v@ zoF6uInQ|e6?aFa5h@ENx#sJA7#NFrSWbDhNU#QrP94j^YRa zPkiyQ@A9d{pfjDX z=Pn5$389Mmi2&fai)Zqh5o82~77NM6q->^XFYp9I?4`xS-}v;c*G6G5L(cu&ul(+J z{o;4|e(jb6>)-hLpVW8H&W59%wbReBj@&nDtOG>rEI3C5RAv~}E7<=A=e2S-L{QO@ ztsU0ckg@8HIIG*$2g3jWAOJ~3K~yS#iHKbIt9c%cXFvWQKL7u`?{%HE;P*aw-!1o@ zZLNA)H)*ZNUOTzrj^nTW!Q;ZC0kq2k@;>OT-%@tKc{LUan9$P~{qwWIzLMn%i~_Ad z6`&lri)klKS8p7j3ZYSFGNTRvI9-x8KybP|Nnpqpg`hcI%wsCp6pQLm2@kq{WeNt- zBoX0&(a-bpK(7Wu%0^?}_Bu{2>rUY+Z|c2CQ0QaeSm+e9@^igUCp-=^4aMo02Bk?>O0q>kX#Qqr$HCY>W31_ z(#+3wz!F{PW&mAau6Oawb%!`dB$cf$cAxe6ZDS)(%`E^xMdc(QAwylJVQs^;AwXL8 zAW8tBEP4%;xm&VeR+V?(gWs)``jb!mm;3IyZR^<*amK8J%p#Csh{%}I8AHd=8SC}* z9xplY$A9*vuRV4_MsVA!cK-JFJ@lDBd1>K7!ISvHg;Q03y35U3jfiF53F48>A@*W# z{uH#P20@~T^7Z-1i~O)LQ`>pQwg8~r z%A1p;+?vfZe5lw&L;wtQ3DQSE5{Tt6N4YVtrabXdr%lKRh*XI(7!VV{1k&exNzXf` zCdJHpKF0!a<8Aj|d(Ayx`}*IovE)=XHyg*Zye(bLtj31NcqDSets>&tx%u;9+o37l zLPQ5=f^>g4sg!zJU$`;eb!`5^#bABaTM5Gb10pXV;+#6?C*6Bqf%Ef^b=t5qPM&#q z{qT<0amj!H0SQnNDCd9(0g3u)XzKrp;9S+yXtT^FB6H4Yl}axr+ITR}c%v)2J+-U- zJWL1*(6 z#62mfP76=9@7#Md^!+SvKW;9-;5pGBLymCiJgMd_Lo&!v2BZpLOoaTt@B9t~a*mKQ zat;y6SzsIy8DYSK(t*!hP9*?v5EiT;449|E3SfkW(IxY~*Uf(5Ew8)Mn%Znv^sQN5 zuCA``pG5$0gP4U2aL$uDH$2(Ew-Nz@AWLBDjS1|C|BY*I zZHTq#ba6nBw(Dj2%<4A|95@=qeb3=X8yKvopM7d^X~{x4zW0FA+2MWr+k8$!-CFp| z&;BpplS-*QyQeNc;VOyd95@2On6cVJ@I6B)j-BY9IB|aG;kPuK%_kmt^1puM)tupq zF2Dr8{I1tO`OL-N{eQoB$9=B{#LID`&T40r@Z%sJ9cEV*=@V-&bwYl9u(!rSU2X-I z0l?NoM`5|gnEXdD4$5BXZKUb?7if(_L~9h|!V4Qi|9ClOfH7fp!Q~ZQIdai;xdZCi zJhf$N3&zkn=mRIE=#|~X?-Pq-)LqMKeCt!BEQ{xkJ$2;JE9ybb_Y(k^5Va1srlYT) z+5ftcTe70_s5#Tew>n~s5qbbriC{5L4#A-ypn_^{LWAj@QSFKK4wu|o%cF$IR+3%T zS|(X0)|n7XYw0I0KHVUZJwg~iPq?%~D?7xj5#m%{o?BlzG&WgxBNv{YAKSTu*Mb;g z0Jylk{Cu=*m;wUiShzDqap1gLIhLM>fPHcOSuH9hsiF(*Soy1Mee(2ryHmQj9A#7M zxU_4wRutwJPd(augZ}cd6F++7ZBZOL>+Y-_;brkCJIh!_$09qBB}Il9B~)ZAN}P3` zrOo&-M69YzX90Jmb#&tsnmRzyHkd--bxF(caipku*9_e);gix%%8w)3+Yz zN)pWH7&*=bM~My?F%E*r5ds1OLc{eOKhx0mFy99NXN#wE#>o-^Rc8wT=W=t`=*V;F zLT&+o3F`znk8__hBYXkqiJ&N_0fa?3gW~&d3i*W&h&ezlDIgyeE=+zXz9dpmOvAM-WQ?JEEKZVI`2k(>ZpWbAr5( zB2Vf-gg)^-Qi3e&v~Tl-&)00w__hkpSM;rC=a#NJyu0!QLx)3Q5dWh zdBvi+zFu4H<`H_`Fjsk*J@dpHZXA!J5h>+p)I@}vua7&Ob7`-v`BG&k=9eZ8>>Ea9 z8zJ6PPd_%k=brfs-zxaoS|cQ&n%ljy+I!!JKK9US?tT6rKL5F|eeSbg`s?ej+b>zX zUUZQ$0IG?AaSwr62aHKhW#SP4b(H&`fBoXon;v}q8}~l(?9)$uYvp?$n2KN=h)wX8 z;e2^zVP+b`fFAqC@%!$0U^LzswW=8(7yhtnfzWZ7^H7FniLvHTS zwkUrGqe6B6aS0&5=BI0`UhH$>4+-OyGi7~>dU^G4xIBq*$r&>7_{z6BUcb1^7^|v( zLo8ut^8^N>4WeA9S`D`PR;5d2N@ESMzL%dA^^D}OF{};D(sO{nnPIW8zDn$?M`2`RmnZC>dogIQkk+qR)|{T*z!_7F&%$m z?y0pSB>>!-&%XKgy=Tv!-?jfXE_iiBMQ}VT4p|Co2@omKYOz(j<}b*WpschN-h+_4 zi+GB4CRrk^b;^`H3Qs@v!VMEBL2@tnnVFvaW~P{gMCx zcPKw~;ndNC*Ko#}G0)^@Q4VCP9SMIBh&V!IM7GLo_;QXlTb(2cQc#exY)OcKU{kwt9$d?Iri|LI zyr7mW%7}AB%aICGwo2<^;BlXb4522b9WA820C+PP{SJRu>hyE@nU!o^NU_>oXRDFl zl)C6(;BDYrrEu1<#J4@oMntvIsh+i*b6cc57;s*_h;#`E-1jT=aRvA#FLY(f!&z!_9NHrJ@*%5(>YHt=g^&lVO>(BwtShTq2SbDOo-GhRW_o})7+ zTV0&1_A>pKWDr@)U)i`5k^?I%E5cvh5uekgJlS1&(h(71d5-*$IGyjESzb+i$vjVv zk2YL46Cigq>QiGoq>!uYt;O=pl#v0B3mz~ojLL-fuf9L0ck3aV0BYSoq+A}g4`w;+I zexTi1o*iM2Kf4-D-Z;8r&t0!>X{|gje&Cf4^sa5!YW*0wFaf#MR_8nry!~B2C0PAm z{p8zz_Cp`Jd6E?xW6uGyA;NUUbk3=j+!Qy}4(twQcf%!pACU=X6Q^e?|Yug}+%y<#J;$r`C0Cxa(1M7N9Sl4CIV+RkH>F zc%<_@6sM~tcXxOw!}|DT-xo)<{d{tYDf_n zzq9!0>M@rWi`O4AQ#!eQpWtFIY60B+;cxznpZ%53{HG7x- zahuQ!b=qZqWQ@80d!K#ev)4TP^vJ{C46eQ7dE)S6}L#(6BZ< zZOXbB^`8}6n47?h9f7o=kNlt<9gD_SZ1-fjxMaIs(*po&?8w1d z`-RooQJ)x~b=3qwhDIAuIr0j^zKut0RPw;TWPq_sjw5PUACAM;nrT9$UuhQ7UOICwYR*y97WMc z%(ld>&S*rbwN+`_>2zjCnvX4CfK$fBdtuED^C#-Pn%-V0vcH;)Q2DXNzdZk-g)}%3VA6t*tLt z9}WEt-xqSTZsq>H*Q9Azn_iTRec(U*(l5OK{lELs4~>Kt0E7&jDK*1q^Ro-8b!{}e zC)$6dab(Ygu80^#NfOr~->AzwVqz1UvmxU}(;DUk z0Kmx}Z`JIGy_64Xi6Igq(%~dIr!;ao2(`GimI)3dY+5j-DX4KFth3{LcaQGg^-6po z?W9jXe;kb>862oZh*%v_gfTECIOCmk*|eyZ03ok&6yxsV5}Tbw#?klYUP^VX6{pW$ zb7*vbeMhN!id>RtpcNp&FeWS!jn!UKw`qqtVMll~kv8S|(S4Ioo}OA7E$8wTaE4Sz z1q_jKE-KwcopwcB>nBEtm=Kjvj&|F$(Y@Sui00G$LX}diGzLlcZ`0^hJ~G)`UrJ6r zH*?)9FAOzYOsN@XWG#?m!UN8SLmffDm}rwK$qK6g0&-POfSDraeqgO-$dzP?^$2ypk!Xa47V<-FD?LOUZSY={5w}~MtEkghx+w@5>IA?MK zV6Fs!n$u79mNf%s^^C0FT)*z`d(T##2UnKn8`ti1WRc0uIRWm6#E=P}s&+4%asmJj z5jQxmRZ&z(9t6&mh#*BYib24GvshLid9k}b!Rt*9hyCDq@e1&sYDgO84a;X8B7s5J znkN(icIUF%&MWRY`fuCvyCI%iuU2D1%EIV^c>q8J7uHx53*WCdrxGJntyUwVm)hs^ z$N~XyL0SXj##qRE)`dYJ*6e(6Wc*u?Nn0w;e58J9k4w%OdUWE#>76@v-mc9u$DTwT zxG2;UoJr#J4-Y@#oVz%;@VZT};<<+KZyh^S-@U!>bI#~8m0rY{ zfGcd?3oM!1hQPYwpmuOiM12tt$)F zOV}?2_g5?;g|)#M_WvhGVGcQ}cz|d-cg^@9Npve)EvzkBvPLH~Ffi>Ue zHr^jDz0esE{-nQyVMDv1OR2S808V7dtzEp}-F@Hp&$n7f#|vPk)-hr*@7kdqoonf{ zW1w|6V71b&x*z~jRCUAyvc};6Sk|vxdttvTNA&=<${9s{otJIQlfiiEEka&hnza@f zA4;2FbJMx6e*W6$ADemo50%yl(xovPqgn;S@WJP@VVzL6tcH3VJpfp;J+K-o79xT( zt|B^bD5e8A6waDFPXk56lGog&Qlhx%WjP3WunX*1vFLZi{ zag&#-5G=f`5f&g^0X1`pUDneDZOGMPt7EL)zjJiYSU(t%mXG?SF4s!%>$>Q)gI=1J zR$`2UO-Ihc#91ez#1aT0SM(ZE2d1O$G0hmOo)X5|UN?=x@W}r7{Kda}{)sd9-E{}R zs5Nm_7+qRkeeVZ<<9l9v=lA}z*U#?UG1_QuIYTbcl-}&j#FrmG9Yr|O94(8Y$tP-PfyGCmEpt7G^#jX2Bm)~Q~53A^ngWi^HjOUfg-q{?JXNzPiUy`WYJDQtmKDKZ!J zTF2$fx}BBkRd8VB$|oSiKd${jWe%w4imuCBIxTts4)#M22F~@P0JIvU2bB`5bqtMi zEM}KXHD5T8Hi1i?;h+EeN8bI89~=H!XJMtk*Uz_BJzYkSYi^|-%0D}D3>ko#^t>0+ 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%0ACk?Iwf9r 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

R% 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�@ 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

%1UdL~g zI_oaP%h~?%?#t1}Xme2HTE0A*?;S4|ZL@Gw0Dx2i3yeHcAQTH=zl`N{mQ)W+;h*_ z=j^rDUh7-m7lRAVT-kX3Cwk9y)e7<27-LI4=Hh=4He&uid+Ryy@fBv)o)31Hz&h-H_ih&Iwx6%vrD2Os4X8^Ey_sG?lv|}{^ zWKMBxry@@g5eb0{&NiezZ`%7---{F=1qc8R>>*P-0Q~4rU%&k99svBGf9JCl!jTFg zFd;E4GtK}2APCjCLGqRdYD1;?1^_U|lJt;toX8mu62KYYKOCO`B3pXJpY31ia{Xg# zFW&Z(FQ{`8MYDHa@m)f%cUP?w$08n5e%K?VM1i$3D}^< zGL^P<-p|(%F)(d-x5n;d)-t|R@qytz!@HJu9LobslpMC`nKtx$-EAhnuk z05LdQ&l-i@;GHd!x6%{rKzOeEd!C&+IyJ^)$FD z2FGQJOdMANDI8Un5LgPsx5^K`SACy?c#3}}V+mvE%yf5ty(8G#<|YD7Co}K8_d#-g zvA6N4ctAh^kswA?`>5Zu;~Q=-_4wKLt1sp+boBw_RQJ*#hG<8X&`brL;OhVYAOJ~3 zK~(BIczZ7C{pj%JmPk0p7MuIXMp0PuJFvG6qb0dEYl^0F&`Nth+I#lJ&Qr?|4ACuW zlQ2L;tu;syhW(h+&h__y|M&jRv-t+u`n?a{^v;f)eSP@yk6rl8K(&OA0N^I5jKLW)#X+xX^yFYq5e764k@cnYpIS)#aFi!3{cJ+YyXT|CSd-qrT4`lH8r=@Y&Y z6E0L=w(eAqg^(SV#z>$#5^4ZQ8H^my#fd3xra`xtmytxuQEA%xiCs4oy{j1GF}NlO zYElgcr}bn-U(}DZIzBlzy=P7tvCE?7c;a`tP^Ow3<(;2o5qu49=B-!JfoMtH)iF9? zf`AdQh$5g2r~*rY_a)nmK_Q?fv zOv&>=3$)fuTR-!Dma2g>b0L$dug3NU$LjN&KXxHM579Tk4Ny{GDBMm`h4Fmk?OCk5qJ2Sbq&zzf6r-&YxA*kR7a2!iv(&M6ey|Cs!A@93MV`Wt zxUWNWRUd$9P5@98(=6{Eokwul7bz#$b;nt(#*;RSbS~4^hc8Zw(y&88Kq)biy?$b< z`)Sg?|M1?qjf=Ntvl;2DS?j5Mv#;7AhSF6YVP4k?Q8v8Q5qJcwfD!~Ch!HvGLWm>- zE{-$`AqJF*?`K#^Tl(QXFR(7X)>FnZ-4vhvoAgF52gSB6d?H8 zSfqdy8_* zm04RL|N8HJ@9calo!Cnu@}*wVB<%)olLazn#$^n?In2)E?D2&0m~@hBoeKc4Wyg1E z0ssv8tNN*T>$?tuL?2MuhP(%2eX8|UrYout2*l53gKaqdqPJ4FysNm-OCeZ{(el2I zvn)-QRAB%>ix#taEmxo~leAmUSD;Fl%oH^Mqgw*K`C&w2gS_RW~<%XV)9)f%Op*Ss4UA!b((`v!G+}<1>?$vx~Lx(^+Qv;NMvN08meBE822x(7dfuw@o=(JdSb66@PA{eP<*jdO*Sc&I0Eek=r!Nb-#zY4I`n;1jrOQ?O21)@FQQnBK5Y1t8D6iAqaY?4G z+|1_1<$icBMw-+(v!bj@*16)?iL^N5@>=)uCEfSlpO(_I!S%BI3!N9aJ)S{ciXEWa z1f%&(3JHjtiQKMt#?Ar2FzbJQ{l(YTUdRLEf_sKeFeC^FlkL*ANCX1LfiXl}RPl;2 z8e@X@03hab;iIx4CiusH@!@ZO_0C`aH*f#)zrO$P{@d=q{I&hR^p`(u_X=zH-}q}^ znd}M(oN#r-RGJYN(uFD!k!U`fyQ<)UIFmfINCd_$*|LdqiL1Ii zpo}?44lLL|{EOckZqACC{vZGAFL5bPq*)mU#?hH$*{g=#9Efo?3*u5IwN&}&(J-7L zbb&MhAeV{(Ej{98SH%R_*~!kllf_m<7NcM8kdcWuVfJXklxv^sibMfGPqfy91b`3h zgO7`cH~i=!4-nP9uNXrXDt3t7!&6gKcepE8yo{wa@#HmoS2bNpjLRcVKdDqEHy?v{kOw0^`m9us4h77ul3xr`cdwD+HWa2)t_nof*z&jUX{LTOQZ!DcHxEdJ` z(IJEJbQC?d#04N)bcI@Az-+C*x?dRpLZl9~0KkJXyzBU?TGq*!%ST^3UDTthKC$Wu zo`leLb7e@0~ts)r!03lOEtf$Vab-4r}J5B8* z5=7rg`JHX}T<^K2e6dwNW?Xqw0L6wF`^i)TN5)v#uciSIkSQhD!t`rmh>W${{=!>Z zZz_t^T3f1IC4N}`eFeY5H0SeWAMJNP-|Lvayp-^hnnZPJ~P4ygA zib<={)>TqAxB?>LNE|r;Nbxi%bYY)NiHC{)Xi8dm&{zR@0Dxj%7-KjOfA|;P27ve9 zy!7F_FDfNZgp-VOrL{Q95k&xyt*&O^Ijd|;lk)N2o%3{=I!98V0)&p`bg5diig+cQ zIO23?kxsiyVymu*(THSC3Z)NEVu|9X+s{h^K)f4vZrRa&KSeIL?HB;a&1^ip|5E^I zWXu*Trrc(`wLL3iaNd@|8;U{5bagNG;dDU6$B!RBc<{hgW-& zK=UqVvS~3`yfz!mSyW*Fz?f{sl&sSrBXE?h;7|2*oO}(8GddkQA0sTg3>Giiu#d=e zdc0}%kpO_pbm_ugc>bAhzV#8D!IwtFE64b$<~^15kMzKgOsKq*aR&O$z5Qpp*EX_q z59jwwUkKeg-B|Ht`(X4gN0TH>@a3iPsA1%C`|2xepS9j`#{eMsnhC{)mSWw86|@OL z=SQ570AMH1%{>k}WL=mZzi+w)56fKuSckPMyr+3s%Sk3VAb96h)@8_wS<&E~J*uVX zH3s|Y;Of=(aWRuMGa-h%v&R7N)aAi7e|hQJoO5^YeFT8tf4u9ldb)N0560yi`}gh^ zI{=Wza5>w2nRPB;(sLjzB!iRMv53Gp5OHfU2F@_+bQPfk4~QZ{C$4>_f2lp_GcL8? z$z{m3$ffst?|P4}!rjl+esT%%T&Ue8?poB*k7aGe>T8w^$b}2;#uCxXKgvy#+>gnrm zOvv=eL3r=9)`>W|s&LuJRV{vq$fWI;_$boyEwA*&C$2d-E+oYe>WQl+F<4hmKSm`^d8>o4zJ<4L9-rnOsD3W_wmJyIn^k6XPb@E|q6A>9>8aFa}0X^%s zY62?D8D~CCw$pS=C3j7D!{b2(xzp))y2p%yO9&(-xtZJGP2KDA|qh)P%*oP|j_^AP}+yP2Ir27v3BI z=yV5z;pW{(C!A5R!BwG}<7k)E+Hwy_b20uD-aELOF*)edMY_D9pMH7pDrfACt#A1! zQVlHGZoU7}-p5^@_ggEpAOV00eFPm@OV%#6o~GyUPmQWoXo*LGcs=b3{TV}dzlk>E39*0d;HWgtl3r#jGc%QcVI&00xqj^yifJYq; ztCti508=Xa%-Zvt>R_9ag;aYcBAbQEQ6LJ>o!fZYZnA|$+`gS8Yn{jQEzjl0W3xS< zY-S(Tfo@kgbr`B?m--oAxRzddt#joMbuL}=-Ifs|lJrs8zz9S{9?45dj3bwgLsz1G zF@5$@_Su)R=ks7axr`>2qO#^FFK#MUVV}R_)u^w1TkXw~W;ROIN7XQSb{RcwC(N6x`|K01r zB}fevAqMakf(K-=nue-?xFCQCFmkaY0@JWFzdwX?VzD-Z%+n{utz4rkKLNiYWLg*d z0AMDO2vn=d`3hT2i(-2HUbQzz&c%m!_gikQ6M{hKC&`)$8`@nJiU9%>X`UB#006d- z7$u6%%o!89r59X0IWq@jT&O{oOv4X_3FksJkwU*eSb2cdEpv(2<)DR38{TMSf^j7edA3RyBvl&gCJ}^;H<=b^iX({{XXcGlMr5=3 zWMLfqkrYCfY~Hzd`@y681Oyblvm4S*YXg8>B=Mw%?h7xxaDTTdia7w7S(xp`X`!uJ zgKj@NKVV#jQ&i#rAXL_T-fUu`H;ul4OgiVE>W=oR+WOblzZfXIz5C{JChU|&z{gd% zH>QulmtS1})GMrgO|Nwn zw9`}xA%m}NiO9I(pT7FckL#CP^}#0kVLkeAa__yJk1A^cVAtR~+vAI!{b$;HmbdPR zt2&`!GEcA=+1y6{>_+Dcy=PxfKXcwcqkLD_TpNfk#CgSiR5tKHo@2&ZFKvG2xpU9( zPM4Am6(&d774IrU#+cBONjLj*fBpgIFxts~=Qlnd=LgAjXWdaVm^Q&NFvf%sP$;OY z7`=1*i(B3pqp3{eSdS2>|M5QX5xAvI1S#rAZ9GSlo6CJX>rA1cZTPzXV0U-7u4o+4!8Y{^gN zlqI%G_c&5iY&r8Nr1rL=7#h$l;~Xdol`$>=kRr)M0{|g+{(wy?W4$ihTxVA-RF+Br zAn%w;U~yL!M8^7MS@e2+ilMC|04(Zsx!_33z0po9%hSXC0YfgSZTUkVP4MFJ_JeMg zXcRzE2*tP*GC{@}7l3TC@49Wha&t`42c97^M<}6I;1@-$;c%4_GG$zFp%@n~2Ho!F zSxZSRKoU{I#29?-UFq%g@$N$iJX8`YNBJmtmn=UMu#|L48U%?l2+ zTI-2iBR`SiJl$axz44}CLN(t1L?RWj+md(h&)OM0)xCOS`~d+BlC{$}9ta-Iin+0X ztfP28ku4?hpng!C)pE)h58lM!7?Uf@V#d}4;-@?g@>xT;=R=zf~8b^}*BY+1iEH zxu^2YXF3-zidLTXj*?|*uAfSW?OJY?Gm=C^&N?AQv)LzPkETT+x7jIDW($6PC*<1A zJnzW<)0ho;YbXR=9=0y#8=J}IQ~9L})W5uTZ9}hh;-CX-n{F^r=eKr8ckbRD4*D64 ze&XX0 zLWog-XDUOX02xnm6cU4lV1c4_0i-}voo~ynXsNIXC0wKiDnuk_qOIQe#s_EO1Y+>P z)kI)tC#q{qsMDDN0LB*P!1mt$&24Dlft>SJt0kp$fjS`vz*eUfZ4CfX;5t!s@^QQA>=`g9X zWdUb`j9&<9>f>_aHF(DuV?r{axJ()V?D24D@-+bfCwG+Nlb{u(0MN!E07SqVmlMQR zj(zY#$PoOo9Pxr_sY6vnm1mHosLWLp z0N{w8SO}|V08gtW5&=Yto{8ir&J{9KNmplsZl`zDUZr#%LXa30)d0Z7v8J>yZM9P? zVpo3Txt(&V`>oSG3PNQKJx#DBP^1`~nG4-&!s?ZGgp6Ok(A(a(naDTO^LHj6*WpC) zOMrWp9!)0a+u4OqtE0r?%tt1WF@FZ7EEAe23YEbbSYQO9)n%Ck>XfRlc*;;90IUS< zGRE(J@bOZ{S>=g$W@*B;wU?Z@&`I7h#xSADPa8BLA`{urVQP7sP*4m@y=}qO;uQV1 zNX4ZK7oP8|u^D3}%kpfo+|PyDHS`Z|-@9Mljr5&`WqOE;hMrVN|5C9XYvOo7v{yhM={{4#|zH?D3nPutGbZ)>8oO6^3a*2%V zEK7ylw=wVZKt>Jw0IF1q6O--~PJjzQ#yF&dPiDBt`dKwONPFG9`|$Rb zKbq2r*szT-CPI~h_lyg!(r9al!Rf+T+iJB&lPX3^S&XXRjCeduk_K<8`Od9se`Qkj z>0bJ9`Xn-J0w|~*&9uc!6~-!zHIF*&*2U=b!MFgHa%PT7n2094X4QwsnL+-Zntjy(VzTTzDPVGn4m7z-hsb!L8Ta#n}cz7-C!4L%Y>T&ac%C(3aLdle>3Wj%I#;e<{_w`FsyyM&ye*pi19|Ih$yL^@ zzEZaUKxchdpV>7hH181KtK19ymnF)_^9RQR;{2o8yeH^FJ7s71$40{7ENO}8?HS!` z2X^<~N4IY+Q_@J4FApOkg~rL zI{6NVH-suPhnM<;AME_Ww;z9N1bKnInzEYGDu~))Wn*PyMTudZ>2$WYw_?UIE>n?o zBR;ZY8^e1$Z#_GB{+Irhw-Mp?jrDJS?MKL;;#ZBHMUN_#eBFh4^GU{KOQo!Frc0z& zOn}ggF;p1{NnF;BP)OhsQh*8aBzyHICSUl59K;838aK%$05S?d5P-^R z4iuTrWd|S5-dhhBlfVIhGr71%uBOANR}uQL(;Z3(fK-epZ@zzLw@{1Axc7cGn>9GQ z-LdIGTcPS3J-6JykAT6qK_4esci-c@z6&xP(?I5(WCM`1w+cE~%1gdBKB0wX5U;qG!Xhl;H zLR_;ET!e5c=q~v-=RC&HYPU;w2HngP^M*R>omQ6ufILgud2(s9RaR%Nmz*pBFor^8 z&aWu`MAXKS3)HkwXF6{OWb}X?Ha**FLNSO#9E>rwl*a)$0wCkFea{k>47Kj*WG!!B z*i^ma#o$X{`myi7_rYTM0+BUIVUcviVn6Z0pV^9n=YkC{4QE?3j`DKvWd`f_%W!{I z-k+Ap#D#Xw8DmdW;T9_MW|>f;F)ouQ3#JvbX+Ok|CA%&4%sF*slij#qzIkuy zV40Dbo>YfLYVk5tc(EH=(j#IkYbOHRSvu_I%5MAlqfm_mocNY^)sxApHCE>6@LnSxw>`WHFpt#*D8@gP7BupI&57yk6O zTOBjnY5mS`ybi%p^yJJ5NLe!iTmTUuK#Wrdom5fqC^hu;gT3!>;8pD+(>X1yovXLi zx-HCP#RNP3gtC6V`?&IWCVw3OOiMq2jwQPRgKO|Kf&g)_?9P}?ASc_k9RGK&! z>W7jH0RTG0Zz+|;Q=97^TLS#|G6)ZT~LY+9W1tpsq}PrhO9 z7xbj6w@TV8akvDe1@m~87y@vN6n*Il4h624Yn0FM{a-AnN7pq z?*42#S84Ys`4}T1i5N=nW-7Y0 zp6;X6WGg8*b$-=_ZL%dEzHF${V9ine3U!X9gn7+o430)G1`dMF6pTHT0A-}QhCWbT z@VNVvf8=`r@a^Awem?J@Od^-$Oq}gO3^B%PHaT3v35Zb0sin0%MXAUcV8XAbyQ3fU z)Kf@=3tix=eXGjTCDp7WTg7-K+n zw+l6=RulFzE*A6sG8gU9nRxF`qJp>k^@&Th0Z4Uan4YCV&bVMqEOA^BMV)q+vWg73 zjsvGgAwKaAPkiNIwsTnF^oOE96n!6k5wLXK4SfCu^_iFTt51omeKAP1& z?*kr(`Pb{aH~h#)ng;^_w2C69xizI*&MZ&+X0piygFnNSi1vK457t;?jd7=Wlo-Q7 ziw`?|qboLh;=({&7|5ia4+eZ~*k97Z5?XC zueYLlCZt}uzUkLr#8y(ib#H$sfPCF<7}OQ*>kvET=j9W^4GB3!i}Ynx7;Edjv&X?E=P^sf zFx9xms3l{run!iY6DYNTSD-v*93&%^dX(Mu2>@{c0X+Z!AOJ~3K~x|RB6#nu^PqFq z8UW*nOe%e_01F+0jmGTH%Z*mTI7cSP)pcz~xeMMT@&q2~%yJNlXy+?lg61)V;O;-( zd;8<*-5qD5B=-p=`@N~Xh#LdF!I-=lE^2H6Kvh)$;JpvQYc3|W2LPe6rM!NcKI!C} z?aVkk_lNu}kwUU5>_~|xZQi*|giPFmdv*1EWz&vk9p>{nJvjZR(>8zXb&r~cT1E~L zm+(Uf_)_w0U-gJ!8j3Bus}>+~X`;IAL@NQYwyb4Xw*q*>K7PmTc*IxJ7e1T6JSI0o zQL+}{>LrJ9iO7zzy{@i{5k(J(dBV$8Lscp)3sJQ%+q0(tR?O9n<68Tan)*xHZ!AQc5lBP9jt2Y zcJKW8Wr%)rzo&OI005k+*I%Yc?DucC*m3N`6+dPOC72nOOJWF8=ZuMJzSk7=xKN9! zVaA0@+A;WgzGtfG6F9a302d3$0H)gCXm_qp-k-&igp6&8T_GaD;d(8F@XnTH!I7?X zU*eoAC4e&ks95}P{@@#TzxVgkq0uyP^ONK8D-n*7x>5_7qdXM}9Ob#t1Mn zTjOf)#fwkol3=;gU``eQe14uZG zo-jo)z|sXm!;`i@cbCt#nvuwqAXgjNuIm~A_V@R*JQLP!O=qos8eEOYWzqrwQ%$7K zv$LBu8#~udZ;vL~pvNFq(1v0=eNr0jz!;Y?dhco>HN~jXGk+z8!JHRkcKolhlKb)2qb(i1AJ%ds;vE;JV^$p=*17-N>OtzFk?t!fw% z=p!5U^Sx<#Id2YV-VGhB1>kit1?V+A-oe!bz_}#wv#n|S!eEK}^2omYr9bxO_y6ww zojd2+PuG(;?DMIk*2$NSi=>`!tEAiT91_U>VC}o#ee=s-{_&$@vMepjD$ABPwnUL} zY0G^sQ!W!O)Jop6EMw-;@ImW?byslUTqY}f`N;iHX`jZB$q;Pw1;$0PE)vMe$9g<< zMRdwpyg3-WcKVBF6+-!?b^g+2fBl}hxvQT!mW-5%Fw-d7yz;!Q{L$KU00;p(s|Fxc zCRAqYsj0>~UD1Nk*kS@9_&RM3Q-Ho|XF?Of!}%is2#Ev&HI}yLknt;5ULc^o@wSWC zIOo7w0OWxJM*xs{Mw~sWM_a`n0x6G)PDwWKJryWy?`{djtz-Z|oG~QFnDmix7Sdf8 zvaftu?*8*PzWUW`({cLO{;kjabN|}^b>*3DY?^DiP-(VE<#)_xzy#R}NeLO5Qb1&9 z`$Qy8Qo_qa{+fefio#_6E!5x->7^>&4zW(O> zZ=!Oo4JH*#Y&@M`iNQ0WYZIo0ky5_+!nJ3fefHMJC-}3qR%J1d!8tRF-b8Qe*%nY# zNmnNA##bKhJeFSoqWR;nQ_gm8&2O*vsuU;&u0*sy6zl83pryU#y1!sauhYGFE=zhm z1kP40@@J}r1L!Zj1X5J*JfuacI>l$>z0yES`lX;h$$I7ZAfw{SSTFR>9_^1+(owo) z>#1MWf&l>Xu(dRJbL0@dy#6Dv^{;(?aP3DoU+wA+ixC*q+<=4k_HO*Yx4(I3>w{j~ zOx;1{7T|DN#K15D009J!p0iTpKGgGSHY&&4)2-e4Ud*MHOoYgYFdh*7Il(+pHLIum zu2T9R{ps0X`FFNkEije%ul~b7eCx(V5Q>BX#^H03kKTlaeaFjzlHQN#tR41f+QV_Y62UW5V)5qSXKmV|)hYUGk!?Lt+-aXRi3AfmdR z1Q&~Gar?pEci(?_Z`U%_4Tpgh06+w=KqcXT!7B2BgX`pccmH?;?jssw05Hagh_m^8 zyuUA5QXEM|F|k+|MnGGf$mpT&1+^B`T4e$N#1MOFZ&HU0&wO!L7*Py9K2g27F(tAD z`jg52{{ANrVo`(`Lz9(eEvM+#E6blP2H;X;6O!yW)A!R)F8judFC8UW-e zy@@9oi%g`|-Z8ZYMF$8%Wk(LKEzS@6YquWVF_kh?1Rvt5yhH?97NugWCnPUxuGwnE2-Ld-neR97rUj@2_gm?eNELU*y8v{kO`G^5U`O!I&l(PH06!p4I(yWO!6ii zg4;H9@5`H?<{?;PE3BxXfZ!NRsQ`pP9^wJ=k_94an6U($ET$2F6D%-vg84&4yyvWu zk_9fCp8ddZcTyCE*@++Oj`$-#nf&U1{OE<}d{xR{{rCT|zyDh=*rJZ6gtOIdqK%XQ z%7knkg9C5iH0}_aSsKVz5Iv{r%JW+Q@IQR@%O8Aa4T1x2f~o4VY{m{{0z$_~RatrO z0RXrHfCuC0u-%~;P$mF`QZJPdKbgbg;bi}v8}sdb0+9lMbFM7QgZx)T;0P38hQOez zs=BIIrUfRGi3>+>Jnq*L0FIJqbvdur*^v(%*7^ki1iUkTbolQxGgGu`FdGvW*7553k|p~$XL~pH$2HG2&r^uu7-<~?P3{-S zUD}tO&2{4Qe3)^Kx~4#yGe3P!{3fEP>%@ zG_T8g3iknk!JS|JE4QD2<&k&nfBV~C`i)=vM?wV+{`A1jEf@lt$}~-`s8a9_gpSA{ zIPjKSeE?jIk(>d>9S9c)g!7x$l{{p6 z#W)-9m4=hU258770D2#M^+Uw1F}R11x4!p-M|-7W83zlr;8my~FaR1s|FAL6tcr*6 z#i2@?K6v?bns>Wh=bV%&0I0OR_(dP0;e*y%tKQy85)G=mQzfA3Y7|#a>hiM z(Wy`c0p+QB6c?&4MyA*cuJ&e5(K~VxA^`0B>37R_-z?wj^43MUc}-vGiOyaan{vOI z7^fR=RMKjy@Vom5`<+B#We5O_qiGd)CjQaLKic<29XB^qggF8gxFXfCQp}lROmvqp zo`z%yna*yGMJ7~F=GnmdiUdW#KBF1NXvsNetgVYtmMYy|Q)$bE5DiNY}BA-WQp zerRuoC^-hHgOJh~Si;)%?rP_C}(V*u01%b1cjEXH`?TMwZ@L=-rV zCS_e)0JwJTnvmho{A^JHz$!I8*M~# zwd6>q0B6Y60l4u%(JfLEb0KkInyhRur{K*8xA*SvGj~+>Y9!)4fCDNB69f&wU}Z$M z(kdI{VYW{&0)S(z6;YBTobje9aIpi`c(8Iq`aK!vy*2K~f7hdwY96pJ!O4 zFzuvCBmCDFt_Y&0C%wDT+Zgs_?~^CVl(V(>%( zK?ZM_X3M@cf}Mr*>0S&4001h+utf%RrlPN-uL=VITFQ2BquJNS;CGqS>7^jJpYMr|NunAi$<+=Hr=LoRtXT#+ubsC{@o(#@X?*fhaON zeNg7Z)-m${005|@y>eF}bLLl(E+OMGY3sDxFz+zNPoQ6s<*CdP7DAxtkqItzx3jK! z4is$zw?vT0_Vx?Tj>%60XNlH}1XN6Ek>+$bokIxT9YS{wo@Vxbc;rc?SUQ-CX)kH+G z*fPFI+D$}00wD*)rYe;rNs=6lkFn*004|PQi&)N zU;=f{gic6ens!70exjL(OSz~NdrH&gyWjq&|EZtnLf4k&Cvl^|feJ#6sPV`rr&;FC z!1gacQDmC?R-OWYkIV+fIFBI^kxmk03<4N{VFHXxQ;vm9OkhzDmD_0=b(!GNdsmQ1 zSYXNexl4JTlbKQhzKXskkpME*75;Xu6$8aqHpY}h@igKO5s`6QPtQVGhv2#3tu)8r zNlz7Z79C2XB?FNFSkhUMmk9NkaT)OwD$&l9l*g_rc*|vyGJRfd^m*r!Iyc}w06>ah zMr{_l;#9ZNNfRnH^&C(TQKO-qCoCasx49C_GSv)1WlY8LJnbM^r8FXAT(AQTm4<2r zxzNowCw4p4SAa2!qz+|rD1sf^y9D3cx5!mbcto*zKJdCTx5S;vP z?#_H?vwM}Fs@fwUGQLD=6N7VR9=r*@4&F4%#0`W?X9K}e^5tKg`$t+{UHMR|$s-6Z zx{}G{=vfny^U+$vh}+R@>!Z8FOXp=>v9^lA1CdM;Uq_X%SVx0D(0h;G62<274zAn* zmn$}x*tk@R&XoYPxFFebH}4Kb(mslQBoo`!s4{aR0TK{#@@T&;T5H4Sw#tv1sFN6S ze<+LHj5%YRbL0|Y03vHlpx9`ou(1tY9WX%fzy&s9Fu^e)56EJeIG0|&di5$m?D6Tj zb61~vX4>xG`tZi){!aeAZ@qBgO0jwIU;~aq0pmjIU@a1ZL;U5j?l(XP!IX2Aq-Sj! zI;wu{>g~Iu&Asi`t?L`#`q~R2@bj1Vr95_nJQ7lL7`lp{KR5hnG>dd%7qY0Kz3f}x ze(TLY^QZne0Az`Hv{$ZBPDX6P)hy2uz!;O|nRAYF{^SNk06=nUy%qpOU>;-)Q3#Qy zX<3%eTE-YM*4GgLgiOY>0+Wq6y^$ox?t@Dny{CXcRWuVfnFs?(pNo{KT+AMq4PvY| zRXxT>GvR7tf&n6D1OSc8Ud^Qq5G=D3QBCGaXT<>=S;Az(WGdP|nhJIkJZK&Z-Vy~N zQ^t9*Gu3T#>TZqC$#O(c+1*#=sKC zS`IU3EyqX%>Tt{ED-g-5`G$;9Ff2I0#n8A>M7GS~6rJN%@=fo8ox3F001zFy ziPLLpkn&Wp^@JvrF~@!_S57Z-n;F}Axmveu<(0z~uu`-}^3i{L7th{(MA{}_9-Si7?HJnaA1 zxQDaPbZ3%9vWjHa*j+uUyVV+F$x%m26axk#0da;02QY#Feh7j@c~amwiWMYzuz@62 z{A?qWjaX9RxD~frX?3f+y1VACfkjr4yu9SS_sn}(J-@Wqh{YNCfW+0G5`?9Z4P#_;_~kFrxCHe_xAX`;AfBlG9iRS0>(LV z7}ac$sJjd7rs0Utj&aVShc;lxaDVpx$MbjBcqB#x9*eB=(hHkcpLzSux4Yv}=f~f@ zLBwvnunPbo1jd*MF{Tm)gA%AL(Q|T^2?_fSoJXitrwbG=BubY}%_9y|{K9YC-rSsj z_|vU&u0MQx=X>9JUh;!yo*N@Y@-~{1xB#J^8)SP6v+xMWTvPEQ5znXD)|O)s061gb z+0qaIq**372LNJ34WUFLa@KOr@=h+L1cDgjs%_<*=Xp**tDrq(Y-^YSK#1ruvDStV zIOj1&0uo##oPiw+nM@iXi_4~*q#_7$${2CQ>q#l3LXV20?wuSOLdt41VVs+Jo%H0D z0mxL;6-`Po1{KcQ7RU=1Su+lRkPbx*4I*daX;}qM+KV}PV8kf~F4S=aDJjxs>|}b; zpHt*WfGj?t?H`!}@~fI)2jac-i#1odneUHg zb-%mZExsm^UTl}6Z=C2VhSZFu5Fwajk0yAt+M8L~DJsQr=$wn5bfzGJTLe8^inw(p zQw)j7)TNx=3t}TLIkQJVHW@VrYU_j4?zC!3$xUa`(~0 ztJkley2#+P@LVLJ89TF(Nv@Kf(78|<6AGEAr@JccF9m+20svDUN}XHdq*6d`Ug@=b znCS~*l*!E3Wz}6D3YE7lqO0j0qV}*kH+wwcv0gpxOcPjk2yuA6p*7Z%+wZ^KAFSU$ z*z?V-!$QB?mr}JY$xI5h*;ku=b}$bQ4l#hdw9G8aO#8-hdGhpQ^gtB71t6i)fm8M&Gx?yOrPZc1$cbXxct>_(Llev0TJ=xtNYj|vY&O03TDt$8 zq&nQ{5^xq{v`vjMup?)uuFdV+A4e_cwwg>2^G&KbY^V98_RnwcpN zgR50KNYk`&lywzZPturRTwO?x6@dpl`55_afu2=2KFN9x$^@NImIN& z``b4nrh9O0FDBsBH#<9j$8&mQg4yx|S72+p05#*rxjAcW917(~t_5EK0M@$LKdK_P8{ z@zpPG{?32)+KZpP3jlxd?OT8F``@HEWQ_4Z;A2xaAq3z8f(HTE?Zm0Yqmnz>I@&t4 zs_BdaVhE8q-+TGh5WP6GEJ83=>hjjd7KU-g|3o zYgdAhVr=OBF5;wKhr1S0^9D3HtL-l-o7h@Sd=AETw7Z&7Yinm zED^JLDTE**#&yCBKZi$Fg)lQOl9L@p6oYSMlBhgEpo(O%BH|)B^*ZqJ0nEdbh7Mw}j*v6KrJ`3oQnVdZ=&*0hG(aIBW@DU{egO=mj)d)bS zLhxrOAOV1aPde+XzE4CU$eg%Hh=FOx3Xf0hKl1@tto2cvpDQ%eAlgt7F`|e}1=NA1 zj%THVR3Q4AvzAMx=0b&FDMn|jCSRvE9 zyZ4KtFE?Hh8?WH-g_vCiGr@z`dtx?R3`n>q@4g&xicWU#*mX@c!-1!$GUQ z-8^{oU@#kJ_wTIz;5#pX;LqHsqylmc5R5GKw79vJZ|B;E@PGZ&?_b@yadA%Ihp+wM zw|?`l=w$gAx*h#!RGk*BSyr@;cTxKv?>!=BdDc>eucioelC*-lj4{PbC(jXL?RlE$ zO!HKMU<4?I6l?42byG*e7O56|2;O@;@1$p~1~Nu5QeZ8wlD9P?uHvSBjOl41IRxnE zaCasLG9bt3pqYlG&-uAFvbL0A=1yj_rGrfX03ZNKL_t(f%#8*^Jmhsf4x-YcIQKqd zg3gwT001IU^tR??BGYZDiVF?MeMHI6!|j1_(en1MUY-k4VgP_Psp?VFQycz6L|c#3 ztn2G&XVF>#I-w-EI6VEo2;a;VSk9fE1BjkuF^N$v0=khh)0uWbcGZ^HG=z@L~3hsE)jB!k6F;WPj z)9DDI_7>BPJlX8-+`ji_tn-d>EbG@%}K@^2d7~@NOiY$27+G55Vz$*;2EbFYO%yT+cQh`9+`z00(AvDO*p`=VBnz=GvELSJ$Smzp*x- zC2#)V+K<0`qrWk~wmpXx=Mj(z%^61!s%^bOhC-)cYdjrs@&L3jMwKx|fe{&l7|7d= z?fF-~_Wi9(vwL^8W|REGx3B*2PhZG#clo&)azWnA1AjcP9+%D3;h+D>kDsVJAO+6m z0RSlaswzL(J*4x&5nfEp7D6Z&rI1o5$#LsLTh#@C7^7m|n$npC5v?W7K+X$3PiWp# z27pY{+`o5k(CtVm8Dl^YW7yc*Dz=`#a6!mSHq!+~pcsTo&iE1ah3pYdMOQ$^+nPIFfbC%y zFen2U5|66zu!>rz5AWaMWNEyB{2BG^H|6$Mc)qnX$4NgeHXYMKpQ>~*k?_mE!0N|# z`bql=MS$&1K<++x3@!iw7wU`-BV(*hL$zFv#{_RNIB)AV5vMX%9X^HG4xg04zcYVe zVX1@^qlW~%L#wznZnS6`Y!L8`w|+34jO5WeBmlNjWm#GPXW+>7VT>h7Ckj~fqv4*K z1;l_WQ*pczkZ9)X9XT+@DC9RgmvgQeq70LDv9T#Ozy9mv|N8fS`qeK7065qy{=t9y ztAF?Re{J`z0#@>JOe;VR!2?Bb1_79mm~>VlTjUy=SFBJh@A0(5(gL_-T%k%KLV)D+ zzqtFK{GI>hmwx?i#$Y~8{?Xt6+5hRk`d35XEq{dv?m>WetNb2k{nj^r^4f3xTmL3& zDwU<hpRXK?){ZvG28K|Qq znTb-0aX}Q%2!ymf0}UL;&;{ZIP?hy`f4(<5c)ULf`)_uNb*nFdP|>@lnrAw7!Drn> z7fmx7-+tH}a}p8}b0#DiqiBuk^os;II2&RGuC~>L0@EsW1iiJv`AZGnaG3;4na=RE zbqoWr0i^x$7 zd$ZXhU_IOIH6P3Ahb-Hq7?Wa+ZG2vJHqL}2T&7&-Tz6X3?CLioGLi)x{2048?KDIe z)j;!3;&1O#<};%o zQYLeI|B!mxg9i#IlTa^=Cn3a{i9&!KRcv>*$kt!md}Y9OOV+^|N-!euLS4#x^{@VX z{iV;B*3c&p^!}sX_x|jq58l2E5!W{-B03NZ5P>m31TIec1aL{aK+aT+#Ude%ED{2U zK-eaT0fG-vG9d&P^!!VAU;X+$)2Q7~hKG-f`6PS!%MZ+A?u-!(kc;pA$xoi>w^9sQ zDjcK$u({U3C-4J2IkN`<;GA2`=Zvu|%NS!?>-C<>^Yel8a!eZK0!Wp3TLKV|4N#m; zr^Xl|<@qo<7%KN0TbXnqJL?y0IRIE!;c>i}v3nq0MXZV!7wcC?|H^Q_e?m3gjDv4t zIy{w}&C(u=>AcxH^S9|hH`6-!#+e1YN=rgJFBum#^$zDqA-cB~VHi$c&lfXh$^N@5HW0Ua|I*BoJPIK~;UWd0J zt9Rag*Bk{RF_>0sw!I1fh&Aj#8qo?hZQWQ$;=T7is_I8u!$BL025*Lg9*|e^)QKw# z(HxkkKwXhbp>m?&PZQ%JGFQ(UYwk7BXJ+fsAFov(7_}3&e}OR$z<|g$7c-=s+`G!p z0?GJ>Y1ZnGzO4sR^&|j@o0s_IjdE0%kE?ROYWdp$pjF-t!6x}Y9-Y44H2|p6Uh8nQ zGQ9vGGpt78j29wRb_Ov#brk>vqVGL^`;nc0c6cj#Q;#2e+gwQpUrN>_lK{X1zrOau z$K^HvD5<27o9SkDwBt++VY)cgl(}*kESh<}tsOYP4z$Q%l{298O`MTo4!pzUmoB}k zgqA8>UBj7-MVuBfsj6yY?f&on-rnE-JOB6dH$EbQkKWt=QOEy4s7<@2HkP;k%Yd^nrdGgzT<4^y} zzw;LW@V)={*0=ug=aQnE7TseV?~^+|-{1Nl{JVd3Gzr~;1Hj>=;tUWd9;Hu&5K2k( zJjQUwGN)3PCsN1P%3^WGBy19yQk z%DGVm>?onAZrxSaEciKgj1c`ndGBz)Q&ml4Yz)zs4h2JoJymIxOb%`I-Hoj@EgV46 z8i_TC|7`ox)lkoMGKidm;GIs+ zAV>_FMa@hzd(6`{WIT~fDHa(Mf`v%dM(5)vcRvPz(W1IE>{wtFLzbjMFdipHZSndP4{=WYHP z09a-Iw98}A^>tG6f!`Hf&=5gIPzs90dfJyO$7iU1Z$lT;_A))dXao`d*j1*b~blr zJ6D&)9jpDV7bW-*m|F69eeTxAtG70`ho?evtu-b9=X{_LLY8H#hfjP{H zSP%(jp*ydA3+`e^s?maBB7)-4d(Rk4;v|G%#P(ub zHJ?uGk`0Q*!C|={vUPF3>UHv4db66AXMQf}tMcG1TMEF5>o755;yZOvWS$1MRcYT| zM0Y?joccuq3gqjH(`ujGdw|HEE@9Gsi;@~49%qiu8&+f8!E`^%ibdJX7u9UG@FB94 zQJ@fl4IIHMA%|I)`4Elq-q({c5F;j<8ohV(*{NwEii#pDrzCkceY=>w35Zv&-OTb% z5Fsd)z+&@Y4rX9!_GGVJR0L-fLUJdIBcHO=>d_8P_P4$;3EU9xnybjrh z3A(8k&OI?%+zz3#`NO^WgDEnhdRpd^>mn4-+5NXqK67o0VtoJ4UklCwKn#ux^~5&k z^K3^l0U{>AR`JXd*quKjid8WGV*ibg7Q3OT{`}4lCT8B##ne^+SXJ?@$>{yO{Lbvr z_hyf+0079LD1GQj1b|DIudT0bWxZ*X9ZgHlX%t+AW56y$nZS|DDWpi#6ezA{Cs+05 z%0=1sbdqZrJDb*P^Hi&^R8>8j%@WYhravQC_QhXW{Lb&a{$Kv>|KsO>=_g8s*S~-5 z@BJ6w{JX#Vuf6-@XNV9PrfC8It*6NVxpRSB6aoOtS^Cxww?BBhSj^J%nZ~viidzo= zzxmhx;^s?xMDP#)$DhCR-q!htaQ2`G-Vnti=krDAb(c@Bn=3e2&WrcHsw(dT0iCHk z#u#VQDNxK4-pl2ntMjA!eu!iOOHK-;4GJ?T-V@i%d0{x*?T;`eEG5nR>jh?C*RaXX9<_7x0O&C5V*Os z%|aGTrx#P(U47=V$`V^oR60NeurmpkpZ1oCV!0Tl#b?M@$4wWj>v(@O%Tt{usu-|O z_5cA}R{R(vlPuK!g)iK~X%LG;Kny|zijA|?Vm#>erOfO3bbPpXWn;5324E=$3;=fa zu*XJQY?_DlAU8wt3{brD!8>bf>!S0O4$sW=&g>`k8`xFkF=vZIdm@s;- zs{w%aUo*WIlVTeHe2C5k>w@=QFqw9TK(VT=@*zFf>jD7Yl*l<_Qs;dXC{`dRa_jTr z?jM`UUERNa^y7$(wWt=Ub8qYO>^!EP0uUD}26rkai>!Sm-{93@NCziXT$y(7PVXBE z3tK`AAhpamaxwR{_Ts0X-1{g#j75+kT4&j&(f}zGsTxdzd9e7{P9OEN%~=>v{oxD! z<|Yj@t;{Da^BmElJD z#jk$!GhcasZF7bQ94JQfaJKo;hue2Q+`Rk2=HuPo3E7K`-G1F0mi=MX9aP<3)$LAt z!?GMUMQ56H`M>=ief#hI?l<@My8qz6`IW!^pZ>F}H}+Sr^E?lew)HGa`;TjXyhl5k zMwk#RAAEZbV}i$xuFI+P9sq`2dGpHI94Ke#;@R~&LUq_(xPgCo5Ryn&MMAu5o0&?M z9ix(i1RKBt==Mu8s6-!Xw>f@19&CO}f>L3)Q-vqlRsawX`y%XFwXL2?ZN;UKNmGuJ z{FEL}X^}J3JhnxwPBA!~PD^u`>oowV4r^rCyV9NSEjpY0*u{v^A8&~m!@skvC2)y1!qV^jIj_S=gcF1{K@@|ByOd}Aw{k=%qFQ2&>2|2 zNI=X+kCWcoWPJC7pT6~#um94OY~L>qIthXzQmWt`Shr3_iUYnPrL2>E{ z9uMd3*pRU%jDS_)>Xj4zSwL(8)t*XEGGK0@pCM!Dt4_c$Ie0$q7*9 z=qzdFOv9z-$QJWinl4G#+DviuhRamwoT5Xxn15jEGRB_W? zdTVrd0drskgif&5S}07vdi9rgXC{}6V9nIUZj=+Ys2G3k^|zjX;TJ|Gv%00n1jm4z z(8^V`7qRRIU>pD#K`^HAF70$+r4+0a4FKdUN@>jk&MkhabBe*#Ga-{)rvOJ`A3_E* z@;pzz{BiRm*?|{d8T^gk`NP?0<6D39>JR?(=4e0v=l}GxfAUA4efdkDy!_(*yZ6@L zd-Kxx;MAte3u7DZobZl~_VdyH#U4+ZHp9(Qt2scoD%Icry}$f7|JFZQjoL3rS#qI} z!WrJhK}U@ir-MxfR1=RY&QEFExkW`D ziBRZV9l;!=F3vbCtAj-&+&E8$Pd2^)2r+o2PmD`M9gwk5Db;D4V`5Ss>=6P7qPutR z-nw<`@&5j$?QP`VH0IFy&2=UjcTHo0^-aSOg$#(oa-SwehQ(LD{!89gxd`)o`yl4o z+OtZDCFi6yGV3~WhA0v&csjiHnM89T@~?jWE9g(!kB+H`XLbD6_ul^E=UzITT+DzG z8WD)Hi7=z&=VL~4t4Bpf-l>oprxS5k(2^1qmWIWsY zT=V|_F3p_l0s!PzH{3tK+xO$Ogmn`p6j5}|9FQSk(mAy}5b@k8i@`PRxtun4?YXz2}@GA^{LW6hcP=0J1eED@5;^X$zZ zTz&HgCxT`=@i$)F`^+o5FTHqg`#kq>-MOL(GF3$G><8U-hF}TN? z65Xq)cIcJFLdz0kmzcBVImrL=8cNFmAeDh3h_IOV^7))P*+M+oGwpL5=u_H1*QI;E zNnP2l(VYa~RM!+DzVXKEU;p~o zPktrVz|i5@14ihMx1~@y0Mw6X0GvtEgAOc-jaPo_BEwqFC%G_McSQQ>xfBJ4xB@aE z#;UeiqO_6#nW-j1r6yJ-tEb}u05Q&#)@^A>D)rIm?&T|&18UnmhU^-nD20{@vjpkJ zW^L{Q2;VG9c}c0XakFgj0$8h@g%&^E4$cvo>MXsyQ5lFKMB+-RWc>#}`tGk?ejWh4 zt+|i@u&Di?{qX(Iy>#=r?R2(ith-?OshC9Y^TutiMwf`YqkT$-gN*0vD~gcN*>*Kw zp2rw*$%49~2}pi{vIlO4Yy5Gs^@SMG7-y^}q9sa-F)1ZvnfHNl-X9DR0swHC1XrK< zaRBm2s7>bS{Qe`BbeKqv`}xxCSDVRgzV&$k&>MZqlKS-z$M5XspIf8ooGH6&*DidB zIvdz}c18tGsPy>g)jd{^BT7@w{36VC+PQ{1Wz{?^57NG@r345-{O6wi%foc7@nKZE zCIkmm0>9dox2NwtEFWy*2G?q@tJl1Q1@t$zs?p-si?>D(C(b{L47CkLaVHr9ut?51 zG)`nGr$~rM6d5C}nU5rMADkx)Au4`Ca6T$WS9(`g?}B3R&Pe^V3ZdpPxY# zv0*0^gTqVLgK2K3S$cG8;^+X!`+0SkOve4us6RUBjSo8G!#q{?bKiLQ?LR)*Ul;O~ zS)KL0k5Y~%*rBTW%8s1SxeLRRGmv8x{)?_o8)?G z&KChzhe&$U%IAp?ORy;SE9`a@eT=c2U7F!t7y6Q)*hf`xZ(#ALP6o7EskhF3{b#-e z!HAXKOhI)77VtD^gvs%}duew^BqCYwp6XIOo!6)60kGw-YB4sZUUahb@xy~bxA^qg z09aG;{C=y?=}=t z5u>+EsM&NfSl@|6PV}C?dF{rf0x0&1WPfy4KO6vb$am+vj9()Ph#V33W^<{s_1?N- z04b{PPK^otBU8*AK-8ta;Pd8Rt^zi%&|5 z0TAh;!W>bI!6D;BL3Q}zAlEy2f|qp|XFU7H+ROjvCx50-8e^^FQlU!8nRZLugZgqcTFaLC4O355Qas(Twj-0+_^M&U4orsWwFN#m zZ6+Fjgo1tbmw)o}KmSI>GR9`8GN1rN5HLmvAp|8OB60)*4XDx-P2(VtcTA^wVmi;3 z>IDsWD!Uph#`viTzX0FHg#^Hq!^6pJZEd~n=0U`Mk&NdjE)vDK-PZ+|yOkSuQ^9D^ zP34p6qa=$qFfC$Jj*@JU*mkL<0HiWC2HjlwwgF%jpFoNhmK6b|D{Hr?WLEg5PS^WMalu_Mp^lRk z!PUqF<6^af%!HO;o_%Hu0G`C6eLS2C)6(`e4z6vVf7i=JwUAZWa;jlbbeg8=cDtJ! zo7KGBS=*)C!J z)9Le9#I#(Ph)g7dyrWj8Jl)XIM5d2lLdI2aH4*WZp;j(4d#S8o!ZxMM6R&a@&0f*jBobA_q zz2iZ0h?WAE9GnBdt^9KB<;1-aqJyK5Ge7_aE?5BIk#BUaDB`0#ALZR=u8Q@AIjoxs zF<$C+rp>cWcozU7Ll#N;=mbM#5IuNL!J|%rfLu*n5dZ~;QWb=#Gmm)ORUIh4G5YYA zv!C&2jeIPD4NjM!MpN*Fp7i|oV0O_!A7AIc7%4td+ z9c~SibtO7|eEHeE>VTL403ZNKL_t*HrS*Js*m;U!1pvvx28h84m0n1p*a~WWSg$or z?INojs~ndsW(uTwqN_FNW12MeESptN>~wh&cxiQLi~{0;KV_jC8x9w~^m0^l0+z|M zUae56x0R_T$i#6fgNK}Ca~>|srC?khI}qVR-_4S@4uGJY(RZWC#6QD1QFCzjb>_w!m(nq_I4 zE*6U{&8n)L&8C^oEIIEiUGNsPUC4!kbU!9s9F4LCQ3?+yh0RTCQ9AXW}ZY)vswhFF6#@9ACiz3xp zMemf>fQ$(VKv}2YoK414>myg0PExg!C`4SggbN{slw6*8WUiUTU^WYi!K-Z8ivF_g zAt3tQ82}`Ce~ECV7`zRxVM4a3C;*U2Ve1n{H)j@HD8_|QnOgxtbT@pQl^%4AQ6axo zECcX?+_*b>Cq##cLp`{xdYjqSFj*fYYgdYEmpfNqUjO2dCuHo`cK*`M&W$G8I(mli z$%D5PgUj7#a?AiAB2b7xh%u&)rLqS?q0T76bNZDpt$*`U{ycDjDg~iJk{rd3CkI2t zXf)YnTzqQCb!K>5Cp-qd>5oF@gvn>q%`dNi0kV#(npoAq1u(u0{#r?b;~j(u-f|zk zR)8RUl%9l01WM!*bp}F%Oi(IoEcp_QUB%Hp&5KDCYic^K(XIEAy|GCpKGPKvlFrsq zu{*dYZ~L>uRMWIrzwj+3L1K7ySk*ymimNm!L{H>|1b~Fkc?TBb4#A?AU09uy%U-3Y zj&hotaC03f|Tx^<%I?@5WlCw6~Sk431i+ z&Ww54Sm(N(EK9Q(N(wS~!G&5q0z>p(P0(KlhJsUFRo?qFO+t)y-CTR-imiMg?|f_~ zlRg4rJXlPWOpN!E2``;u92pP6F$Td$5Q3~>!Fk4kNT@W#VDtv}lqAbjD%C2HY{5l{ zVKC^w^~Rgm`+d)5k6jHhbi}o)elSBbvGW(ZR{_9G$UM|CQ%n zota${SI*Oxq#N4J97H~DY=%LnDF9T9QYlbrpQk_(`Dws#42H>+3%#V9k`e&Y1cUdC zaZjctrn0660I76zrmW_9(JN=;G(8Cmf^V#Kqepw);hIi!Us>WNdaJTNVwd->RI_{O zQ3ju__kh5S7V_!rZk6ThF-DB~ z#_$V_DUKqde`E1oA}VCRtJY$m4SqS#y6;y%1_1KLtBgkqLWOF^vn~KA!aVJsr@?*7 zAd116ws42_L9GTdRFVa6t04QSNN)6=H^pY|9=}_^3xE{D1tc}jNTy=958hhj$nZEM z(l$8B+tw#8WL`*c00^)W7oN3=)e5g?rrC6Q(kGaw^4c1_@?1ZW-DATFORk60*F<>8G+K&7PH> zz&0}i!Bt1-f^+U8+V~_oYIa=IiiCR$U0NRej?NCxWB3@C6uEDx2};9~N;z0R-y1j6 zCK}nj)GM|IOHlx#l-c8+YDC8Q^4yNW2H&(SM~q9Mo|y6Q&U4P#Q5Er=c0jCZ!x{FA zTnZk8P4Z!?5-t<(8UXUP3f>Tfia+pSP01kuT)DJ$z#bygO3z-n#T|cNa$25Uh*iVXcjZ?Ea%+Ti?VED-L%dN zV@NS}JKa1lq?EJS0z`LwI9nVnWV54Vypm=+$$%kiMehH_{U7PR2&Y+8oO496*C{si z&Yf~kK=|R~@4Y>G<9mDGd4K%Q>L+DaHe+jmPa_K<5)qTBO!~{W6ROKa(^NcPmJ^&A zNnM<2;OCqn0+&MR1foL(DJ17Y2*HE`0%r}LjxD%QDoHo5TunROYSK7cbCKwL4Uq!? zX4}%9AV>JHgG~4%OdAtQ>ioh2W($XPX2FFPGVyMuT8l_AtT6LZ(YJQAcrY`8X9XKL z>m*M@L;xV7shP&?5=1v|h@6Q{CA0(pE_ARn0FVM+-1r$yA}@9hMxV?Vm4H~sz#|o+ z|JmW!B+r!403cA^NI!c?J$obloZx~n7CBqe7V9-k2jFciC(bmDjc6SsXdt}3cxdWR zVO2gJEj`U~r(>!>#)Ty|w;0py7V37rd*k^*R}{~^GI*5{pj2c}RkN$b+!)K+JuFl` z9k~_yC!=@_L4?@S4)93G02;qqusLg6Eri$X-fMQRA)hFWikrC&-Z-;}F|747#w7yL z%IZB+r#68YUh0mir-_7NuWsgkw#ZzF zHsHdtg=KE3>H9AmO+2H`Cx>H|bO#-giiilg3fmo{*u~K_V+4_p+245X@>OT|B`obrS7sx-Xo3xr zJ=eYN^J5~Im}NM63V^OpK<7~%YI~6_|BKEeWQnIDse5n)xJBm6ViR)It1|PB_`SN^&I<9 z=y4~%xnJ#XZuJQ4{%pJm3-05(-jQ4~##$QE7-LVaZ|iFuIU>$jc$1ASPkXT8$_YdV zLQ&r3Tx2W?#v=klUV5B_bn%4#&XaqOA$TKHcE(&(U}k}kAC;X631!{5J|`D9uhOP% ztO*FgL2#{+l|mLev%UmxfnwHQQy8gPF1Z+K(KHr;00Kio19syuY%}rn|NsFY@$-7CX=e^tA+v8Fp<4e&;p@|46DlU~2TeR z_YsYwrY2YZ|Lnb4jAiLnF1Xe|?&*v%XJ+I)RF&;2gYh+(rg6J(w*m1$3nVP@h+5(S z9(Zs!NYIu5$)X>){m?wn5{3u51*ltUH6XY~peu8+vGKLbuEAMZm6da5jAz`_Klj6q zh&&N-A}h;{sVjASN|h>4{(CrQ@BQ!ful23(vvE&mD={HR2%l|D=E))gl!H5ae~nX9 z6n?swp+Z8veHz?&XS}mqrj$qf^UF*VMDbL32=+LzhmdwT)MM}cjn$V&^+u1i8n4E& z9sxj*eH#dsEh>@&=}{K7Y&{JShPa)(v55Pt%je_7@DO#z&$;^Ig8~THA1=P(H03bW=0>tS)@@A%#JmS_X+SvpYtHyE_%>lkuWaP1D29A zb?wLzHfm`w=3!PngUhrohEaN$7>ww2byChWO8a|sr~sKYWjz#YtFOKK>gww1`qKW( z$~kxsm(@M=l6W((3YVlbNa_HZ3GYo{JgA18MFb$7t>-35 z_3&Q2)b5;ny2GfGRD(M1&uN_?!3aOmq>YHP)W~N;8{Kdx>tikX|zt0h#u31 zp;TC)%oR-+T!WfzaNCVVzfeO=o;FQ4$-68|l^OwnbuNqJVpP#kcRL;zUkbs8I8Lnt z0M=PrUR-rLkc43ffFyYEeNfW^%HTs_9HTfg)_Z5IbCHw?L05(4>2RniB}VHgNzR=) z1EI{aY&sp0zKpPzflA7sjCUVaI~h+pqGN-Lg&g$8r7yO;nwIj6=pYgZw|kJ&MGXCgwVJwIk84kGl+&c6C1P^!ornNuY#M7J16Nb5IX} zJ-w{XYE_p$aBUnRn6|sl+5kW>NWn!URb9(S8m*lNK!)HL0Y=aVP7-o3OCzBNT;{z! zN6XQ^2fOpu6$Q>b*p$n<9LlH-^VrQY?mDaY7%XY;;Qs-@Il~S=ytk&0Zj}!^yXl#; zmmf{;#_hmcjFfArKFS4%!kl4RU;x7 zQ3!#`h0W1qwHE_`wuK>i4a36Q2m;edTdW)JL05tcdRQ5CJSiz9Hsr(7blNczIv5NV zmptP;%F>owqwNoO;U!{6W3^#}3%YU~$3*Y{!W;_sU)NF>D_}gnkeo8kr_{% zXdRqDZGjS?c>G;7FNix~PI0y-gxAwt%E;C(Sz-x*B6SqUv#B@Aqu`GUN1cR~EPi)) zwBGM=^Z-DZ5R@BT@RKu}$9L|Em}c$m!FI3JIoQm3?~yI9AI&>cfp(q(G@+t7uJjX# z+C~-Zm;v})6nPQHv961LM12TVtr;ard}51Q;n|Z?o{65GLum&NA)|c&5RA>9oKd-C zGE1ZJ&`HT#?XI={+Tw+%_)j)@i4#%e1&5$iiG;Wi0_Su?rbaWRijCibr}4HjAFKy1I08^~PafS}61C@h*P^Owr9EI2N#UWU1g#6!TFQhq zmJ%@58l%0lTC1$xo%NR^g6Oen6LC>yky?GyZgrdg%4kZ;JHkR z=HxyAY=yy!IiDoyRE?My1|YAd+tt=m zykdBd?-#CR(z7aOGRvZl-qnm#M6AM8Vwz7}6c0%)?Pf``USKRZ7xp7%L_|buEg^_V zdQ^722ZR-Ieg(i<%Q*ASQ$lM=d3cSsHVGIrcv6{K}NmH#-7+e+DW5Q6YbCet1Si~a*pynh`4iHY?M%bBv;Vb zu{9iT5y#${cws-Wh>&F&rA%Ary#oM3nbC8I4L9nc< zt8c&dbvu(>s~wxG7~;KUQg}NjtJ~-SW3VjL&go}2I2<6$vM7>**v*|$UF$TKQt(;3 zx>@W@rzOdjxg~C|bQXd$d^f?p{wU6fGiCGp2k$74isAh%iC%o^#miT&E-fv#+gUI} zst2Nf4GHzmQ^7b=Q`gh!2+@hCg$R@}E~JoAOGRx+MU?meA%wKmwnpo^>h*ixhfcej zk9Ro*N7#6GQ{_WvjSymMd#By*BO%^t?abE)H($%|v}q)%u!y$KUn1>~re`lE%L$X$ z7cRfC`BX}ZBDv8z2LQE$&7Iu&;G9cjW_(iF-p2IC>jhS}WD!m`y|>UN8obGi+&F6; zu^t%#M!|&;LRdS00lZPQuBvh}nNBBDBt&qgRIO@NmNgf`TLXxIKsgWIdGEEZ5z#t( z#Jkg*L)X-*V)j<|EHn9@KroG@_m(C}{$%HX$g!_xJ0FN-_MYJ~X|kok+gXyJGT8~@!K3=&SKt2jH}4I1 zlh#yc4j2G?Iv)S8o};8(`GXM$f8 zk&1ioGWlKWZw9dy(VZVyX`k)3Z*GrY+seOrfA{9*&beOiqh}Y+_OssNT12cb2EatH zI*#OV->aa@Bjf!>FZ)(ixF@(4R+#%WUkY0A0#*^ct*elP+D^~ zKR$A{ZbjVtU~PyPoFsWi2&>C6&5r8dI8)R8_p?z26VX9mwurOQ_E@%`CJ>V(5kdr! z6s5|zYtnpk4>uPGAVE)E+M-X(sn6)vpSyF;`Rel7+2=&2eUop&VS=SIHRX|PgVW}? zefL3*iG?~!`gOh|v-v!>Sy*eWH7VLOiIRO0rnwg411q%0Gtv~E4U}j|UX>qUkenm{ z@UYw-n!M$+<%MeiO=3B1swD?IiKHxccTIL#01yN&8DHfI-6NAB~)Hpx^ZW4=TiUDFyA3etS3vi^CuHih@u)&s;ocT{%~Gz zPskDg40X1d-#Hs!ZOU>Ez}RBThlwv=s!SYZO?NK^pO40plVCLOEtX})MJgl`M6GH7 z5Hc#p1IIaIH0X*Fia?C6WE9m!p0rwZt?<%P1%PNY0KU!K&XmAye~L_NSxQYo*Hfs%89Ghl|d;R=fT1 z(c^xv=bZx#Jie322_gd^Ro)4K6H2V{-gOvFbX_wpybl0=&o{(-BqUC%2fNwha>oNL zt&zj&rHsy=$#(5B5v9qA8vM1MNM0fBCcFhvn=oo^9k?Lg7gHp7{>{;&!f(V3Q^AP$ z+dBqC0yZ$Osgwrg>)SbalM%nt&f2Y&IEuFO^7hbpB!D~|mQJ6O6IiG1ks9lu8mR}$ z*m%2)WZcp9R78h5rllLS7C{j-}L{sZxm>$zaeh)0S+Z)rowXcMNgqeCGPEtal zd{)G3ZxcXc4LdN!Gp@E}XaCE4XAlvPG&eV4U}^`)vcd;#R}caX`nY{o@V3!c4j}|@ znMkXurf45L+B&ozb0Z z?e5|7>tUY~Ms;AV#Tx(sh*ep5AR^9?5Gs@6fvS^2QjJ20D7MxTLW?M6#zsC6%JRuL z&00Q$n{VB`cKIRzMm+NgT{hL2x7v(yCam@Mx5heRl@8a+o!po+$yz&V_jq=aIYLYY zlgZ!T`Nw|$3R1GO>l}V)h29?Xk#QFyI-I~x$e*w_v(Q8D-hRBJ7Wwrv7dIW=S7xCq z229q@y-tf4COSCBZ1KFsFU2~rm{M~dK>ltEQ!&C_Ufu790X5CY|q zWb(ki-dRluVNB9vc1Hlv<&AMV1ptsz6HRsbO8*CaFt2U@)2JS7)>{)dx!k_mjK4X2 zW8m{()T~0_uG%~!FA!X%?4GgrIKQB^DT^ZJOvEl}Z>X|c)|b*GVN7LdVbv6wAdxrj zF``$xk0c^sxU2w5Yb>FQ&Z)8*U+n$JrXEg0kiJw^8B*QYo*o>UAhAX{qd0vU=;Y*q z^9lm-l$B-b>nR~jDVHWa%bYV>a0Zm!F5f7riL9`mjB{haAQR0DNW4Qta26;7!iUC8 z$2v7_C!FBsYA=yo-W^V+cxXnNe@7+(Mbs8?TSV2Tm zJM$}vsC`mF9{~8gQd_IlG5b6iOIuBImv_eMl2C?(%}!XZp7WHNy9`(NP*8F||Xfxbg6W3oxYw3$}~3?B)zKydFslJLvf znm_!-W!jrnt1;DxLTJv-YDF3Krt;Q$YgJVWK?R`MpAIM?-g|CcAVfq7ASHxwDQUHH z;mWxnsL@*cV2!toI=iRJ#u(v(W$B_P2`FL z2VhlMO-94FzWXij10q`I31x_=m2!@6zx#Dag<7@Y5;(lZ%vsv;95DWoz>0z_~0=KA*gEH zv}Pe;fOx_TT~F&g7j3)4R}Q zJ-iF`UevZ@9&4+t^>uN+yI3R15kYCK{G{C*6w`L_D{&M@k};ZcvK+@(81#u-NX5%E zoarrY0t~IIqKItoJ^-u$fbcEBRuJ(*>k=X|M$=ZSg01B6WYTJNocE4cT~C|oLaFJu z9^U!#gC~!sEFtn_8+=6^YjgC0kC{7@)r;x;StbN` zoJ4g1qnXgx~j(B8Sf02=}Ani1|p4*FOLX9Pu9jEr0dhkaNc$&Vu6{PLvuUF z+hcvVz`G?K=i`&U9TH{_Cp0-1S1-TF545p)7WCAaIy7C$$0~kvxxId-p@VwOd8Eoc zB9Sw-nCY-~Rv{rssElH*4W&c~4n*wr0|!4l`|Chmz%H`@z{Fk-uGG6(`fzjH4wVCd zT|M2^lg)ahygpVfIYgE7&yM zt{J7?*$T?-HR>&ncgA_11GqTN1Oy)3U^K3^tEbbTmGLIx>DuCp@8J0*M;_e!%Gke$ zy7_v#qSV-!oQ9GTJr2~?O2k{e&bz%{9mx$s2Z|a?J!-&OzmwnEoZQXrC;*J>x24t# zRNg5b@|1h0nM{*3+j#UKgkV%v=aaH1RFxwl=Pb=KRabzduFK#(La2+WbB;0Q0E||n z@mR{Z$n(0YjH*Nw5yV>CS--En-*@IE>YPpq2Y~#+L*F<#&LsG_OpPwQ({(XydbEyY zsJKjVpWU%{Bk|~e2iKE`+D~!0_6Vm?mMHm z_V>kt$nqNQ001BWNkl?Gqc<&ia|6wB1#$U0ljjQ~+=4FJgQwmM@9D*#a05&)1#ldZ=feISQ^G|qUhyNHp} zwDMNhJ-Op{*!7$|K6e@qRV{h}x~=#@&af z^3XILz+TtJp$kI@1Hkccn{&=NtCecZ%!%wO2fEG==0_FiLnT&cJQr%4PsqDURKC8# z<0~8Ntg0r7^IO&Eo7=bU6 zg7?$$*g2Z(w6#*i{bhWF^sO+VS)&Ua043Fud@ z{y==`zg-ud?fd`us(LgI`AIdtwYWzamq^yN}DqL?Bli&b!6cHET3sTu8|olQOniSH*Pu(Ot^8 zj3OB&Ohjc-L~+WvFj{q5ZAxiXmEIXbS*P0%0aUFBrCQs7;OawhgPVD{T-duS>{7c$ zQve{*p$7p02^B|~i_gTteMKlgsD>@dPSYht1HImTG2zL@3m5zSUgarRv-9}DczdJV z*}XTM@hvA5nXuNWz`U*iU|=@){sp_i_o^ZukMpe6;Y>gXtyIcm{n?0w@x(Zidd9p_u-qmv;zQ7NU>9k^hi&n+*1W@jvmZD``R6mK|(?i=y*Jh zlD2b)9@HTFR!y7Nngg<>+2!cz`>(cBm(|2yjOb!n4+N=}q#nCPrPY;)FVN_Lo-VZx zDSJWV+SDWgQ~@YO#;0|iwNfUMsw}-VL`ZK9<$PhG<*i~QsmhWIUYFA(>saRz5HZL& z4c-Yx&D2_FmzI~L;DA8Di&mElQI9rJ4Un=MS1;Yn%Y{}qZ7)zHHk5vCb!D7%p4^_q zY>RVFx*d`VpahXn!9+rtxSMY(^u&2vX%@3cjLV{UTojQM?dk9ey+Uwllum91&f^!H zdzEU635)CMECp$`F}3%WXpWP|+f;~XDUHsyvMwRS8O@WFa)A&mSJYyZbs3{R1Y4K7 zu4LK?0L~gh>3BR0$d;E^taT8));a(%fDRgUI~Zy69#fY5sM)+^SvGH1#8wlgY#e^uY@u0AOnCu`UQ9i1^yZ)<@U) zxSrmAID{+(fB;ZO459^a#=#^_E|vL&3t8IoyT!LMl{s`0JrdfGYQ3P;QSLnwVOgWp z!!hfD)xZQe4M?rl9)J@>N<9*q#xUdFbaZYdlppUdjS#j9H+OFJ-p|!(dB)0}P+sM` z@nM1wsGJ{WbUvG-+Fo6#hI!nZPXcX4kgLK*tApvI{t4EzMCs7_GHL25-!JQtU=V_{ zYHnWJ7_)X}Eia0)(r3@i3W8`$_pGHJDX}iqY|N|K4ha`HT?7C?%E55-i%cuZ9;t;D zVz0H&&XtLArlLId)=Z~Uf{2N3XyKF)7XtB)GUlCm{CIb1K?p9bF+gd0X2EJ>N3|4! zFi}h=f^%yOm!g>F*ruy1%OQaG!8ykQ)Vz&$2SnP=TIw5b-hncmWTH24uxZL=9$%AD z&ByO{^BwR*f@8)7kEE-#3!$v1ak={u2rkO%jUp$QwK{q2tI24ytR!<aGll*xP|= ztsJ;PT$r<7Ewx(j)ZOj)ED!*H=Ri-AsmYabOJH>S;jSTx+ZmRurTB*f_MO~Lht4?oWYio-T!Z{m_#-s{~ITSQB1kw;}xm);+ z&B?UFp&t*2SXO##=g@UmIpfh>=?w3z_lEIUl^ZhYHtBdoB$OLn?v;y!2beabE^os( zcK)ehr^NZrlA_xzoa9fASBTNudzKuQS!!D*zT`7Z$68o$wJtKNG` z>1Z@@HYti}Sxk+EqO5ip%@T1CVKv8UxSN7gs|(`|>|yT?p;kl!7TXBvEi z*Hz(=#m89NLx8(?H$4}$R<5!D;G8qY2q6d|Lnt2)9$)RwMHp`7Tv41Io_yzi`J98Ov0odLULy6bc)4sN9B1qky6^6 zhPT?ey=ZziAobqrYD(M87rTk*9@*AgO^z*&oVEyr?V05S?<^o{RS+hE_k=P+ISm>C z=RQcr*hr90D-+V@d6A|GB3NBfE@|9zc6-M~OZ-q5uQGXvtPGvzqa^7JhmSzS03gv_ zi0a$b%9`2&ksXw+tu7gl8YWiri4f7F`?uGxttzFXNE!#6AOcV>2#Gq~w5m<;%2|`e z$&MX}nx-<*Dn}RE-JUU8#EJJ|G8!qZZ(P4N9`3gLi{*4&O?K04VOzfF2Tx)it)Dy7 zUh5_4yQ*koc|)?)8E;l(#p&F|9U)cWyFV0Q|lG`Tt1! zH=-!|@_SzVWB5n-&imi!|2zKoLx1~UUi()#cJ&lrhVSJE z+}POYUVxwZ@BceQWE8oO5CRYyj5^{0{#s~v0ivPVAv-M^Kqj;Zqv*gdMQ=(nyp^rGCoHH4>03bL!^chDJAJ(0r5{QW@4+ps`%R8{2 z)g=(lM`~ymvT~EAtKQb!myAh^1ON_d^l8>=cl*RwN@+$31P6>8r6@(~h_j|B#u0Ce zC{xy)$)H>Z)vYdoq$q7Hey#(??l%%=o6(Jt12H!%nRwkF2XZU4Qqx zZ@ze=9fuczL9Hk6ZiP7FmlhKMaOgY<%uxu4gffu?Z@e>{Coio3mv4`5-kt0v3Wt>c zZ~yM!EiBAgKb_(fC*jLq{_-FG-~TIk2Rwpm8mz`9qB=%ad0ySsRAOGuS>{tF=WC!K z9&fB_5Q3|VUGH=Vp7EGR*+HO6nK)j8N1T%Z;4+5C;IIBd|ZoZmxHjU?qE81gSQck;KcOo*7NslsdkXtyY4K_B) z5FFb#Pc&-ktqR`eli~7Wuh&U8Hy+hWS%)r=tlc9lYU-`vY7#=99sS*un-ZH4Tkud} zwJFRF=&`fv;95xZb)X4HJGqx&Ehum>1OfmMDy%91peUwVur$tIFVBHHXFcSiM_ zB6%!?mr*;|i%1Y49V+b}_bO%W(B)l;Z0D$xDOD%DtD8wmF@jM6s zjprbW7J+a3d(p#eVQlqi$VDrf2g$z%YaNRKEnHsCS~Gi(7}l*M)t zwX(Q-)VM;-WSo&uCSn2>_UUd&ITA*BjD#@}XRWStMn+Lpsp&N5oNw<8tf?uFA~9#3 zQJZlpdZrpMUqymbLgJ)DnY4%Aj)71fF@jBW8$1hp(>-CLE_Ncp7Zw(^wurb@ZdAJR z&H+*+1QCovBnV+o=*XEc-p+$ploDr@(F#aK#O(l&A3fR}?pAfRjIiwWQg;E;Rw&D< zs^TC&Y|RZyF1&F4LvP-?rF{*6X}pleL=b-KaXqdO0W4aNJ{;2UW0c2MO(l`nyDvWb zBA((D&xW%u?5)=W0BEH{2tavIhoa2)n8>^{M&;hyWHEw5SNc8TyIENC)JWZ^+?kqC z&UoDLgia)B%@bsqOIHf>K0H9S(iuOTPsTcQG=Pq%%6zQ(%8|nQ(UFAulS#X?;37TH z@pZvZRiTVEc;!s3 zsr%0zfbd0D?6Dzy)tCCr~CZqxU%HF}9}iPJ3sX zHcBotLKx+uow2-{Gr63!_Gdh@x^h;9;JM6>9`Z zZ4I_K;Mi)d0|d^wwN6R_08FGvSln7TclMn1m?Uvk)tpg}PnQeUD;mjH;5NgXZ9PyPav?YR zcXK-0bsn7$N=@$E{||$0RTq~iIfF<#?G_+X&KVb!Qo$}Gp*+6hY~ifo02L6Cc5GQ( zxqRvW`tnU6Sk{3t((g#huq+2~8Q9AC3j2xeYh@(4l7>awvL3BfmO@9 z(OOw3wx6p93=t$0wSSMM1}@XOI58IX-WpXHl_L@^GbUnH4guiN&;=Y>`p0Pftq-+Xc~S0Z9?2$q=K?>?M3+`IhF z>w-S;N+x_Mc<0R1cck7|G7H{eaF)a!?nkCk-t>sH(NAh(XV|AR8iLwsC;H>%PtA8~b7lfRhOma%0&=W3rUFNEoR%KzdDvO+k zYtAJyyQB3e2Im1Q=b4ak)_(aqd$RpV3R)X~>&}=908Vw4BO@UMtL87WlDL1VccY)q zDF&Y66wd``0RX8uvY?#x^?M()o=7MXo-gg)n1!2<(tpH0bn)@jUBt@hqpADnlR|DWXWWjNqb9NFh& zH2I(Y$6xx?fANXg!PeBYQH}rr01>ryJ>~J9>XWq&5v#hEQeM4s5debU+qu`EhTb`A zt>J>pI5IZG3~D>ka@*_mj3)q&P%fgDcP0c6Nb3FGcFLu*HDxqmWLHDm7eb~o*|QhL zU@2G!43GkV$d+7Crq*rI3ALa4XD{%pH3W~r2JZzS)6q`SIyW7;uYKeH`Jo^DOqQOl5eM3JBYI|K=|6t;>z2L* z&~BxoEENwqrOfCmr7f*3i%)~oQ@n3%Z*PC`i(ed#MnCZrKk?%~{^Q37U{g$@Y)`;t z9^S{?$|Awsu+p6)bF25xnwk(Afd1HzfBN@+@AuxvmpH{S{Mn!V*<`qTs!TS(aSC%)oc9xg=jiqxvwOYH4CmU<4YZSnj&N`QR>I~E{R$>s$ z`ADqT{2q^6O=726sg&9#(Ls6yy|a`WN7A*}Zqy6sp#}gEwVDPH3=WVvQxe(+K#Uhh z+wZz|hoiV>Z!Yn3E99&-b%099^FjzfEQ?$qQFiq3@$0XA_2|z zAG+Pn+2xhWm?TS$@rn0nOeD{L>tLaYKZFv>IzmIzDDgJ+s*I$2~F?Rj>_0N6obD#hG=T}x%{_qd~Fof`_ zPkrjhNL!aQ&W=QfN@+XOgZuvOyH?iHW^c9Vt#(#9t3}j;;0fh(n>bJLJwQ#(ESN~3FEPdT21MxDb^cfISt;bh^pyiM3}TLIPJ93=gyo17slg}vyL+As3noD z*#!L+K^Js24n$ZFggiBWA1Sk#h=W5@%A8fqmq6sQ3=fpF0RccnnKd;H24-~fz37x` z^GF<5X@RzR^@;FZ~yJfFTd;n zlC-63<*e~S21*cMq5t6@c=^A2{q=vmefKL8jleJk5nMs3yL0#cLYGsh8rvjoO6!#O z&+C74icezy9mtaQKN&eB#ojOG%Ra%CG#&8*jXEe5A3yt~CTd8?;hNW@p>? zH@6Z2YO1WMt*!_Yl*y)d012I2%0I>ThGan&gR#}6QHA%Gi5QVIZpjB@_Uspf&L@N2 z!Jw@4ldU0(dWhtW@7_{cGe*7l#v6}8#^)eJwKh#tQzKods|oid(By379;gWRsm&y4aH<|XY_|2Rm6U~|RZ24eSQ2NP(GZ+c zDgYuPr^EqHipRHZy|dK2MhNkM-kM1e~7bpncB@35JXI!yqASTe-9N9GP_Sw@)AQuU^nju%D-H+js@@IvT zQA<~oIEJ{>E}cRuAzJ9QIq`u40{|C%9Jh+;W-E~>WPreiTtot>R8ed$Y|{p@E)qfx&ExR)1m|=k=|l)?7JWo! zt#(z^E;t$0`1^z{bYL=Rg1Xe!u^7KlgLDZr!?f@7~Y<{Lg<-C-dOJgU!v&Pk!=~pZw$} z-*a%NbBtTSxG|P<1_0nKkdyUWgLmE;XSH*hGRb8&+g}6#Nt>0^IW#E|wNKLm-&Y)2 z+%ge+XUbZERcRutx|ZT;k`w>{4_#g#0D|XnhBM}mA%v=`%Y3R;RVz&h_1-&Y5xliV zg}8L0(4m4v(Jt>^ar>`j8));c#{FXiTfv^BtXaxd`q3f)4D6P1I!>8)5kMe>)Mj^g zcyFnHT}sKh2msE95FjcUw+spQL`=2@KGcL0!*VOe-FDK>qPA%JnXZSS-Adb+E?;^j zZr$z?U-H)0gL~)K*X}-f0O0FTdv6AVkPv(s`-uSz}`@7%$-QWGwKmF6{86G9p0072qaMl`YjcGc7f>E>i{bLHXgg#pc zl29&aUK2s^^oLPV<#p)3Mj9O||Tx*R_31waGK4WLg6v=gbFB8EwGeL>+Sm= zedR^xc`ol6n)9mD<0}+lJ-c*g_ima*j8IAWz(0IAz0D|3Hr*?$A$HdsgmQO#q2Ian z?%P+dT&?q=t)gN&UB9r-vS&A%oZh*G$=cc)0Q~VE|MAB@_OTE4d_Mi@ zPk;R5AAjquw|?ulek+dSU;M>iJbU)+kud>jFg5ZBf@fS(MiCLb6TQ{%ohQ&BO+r!6 zZFxGqf4`3qQR|4d%cRi37I7q0Rm9O=D!{6oiG*?~(}lf1Nna*?9<^&-KPettSJcW? z%4%&H7tY$cESQjlipJ%FF;?WcDod?3U?|J_Ky~auiaTLgIDkfSn09Qm>{-fX=Bxr1 zm2SLMJ*i3sfkY$~(kWfjBpv97N!IIiuR7}}<&?3;j8@1bR|*h07f8r=-?{?;gwJ=`aw>g(M$)sb#hA()t@W2%t80txGmBlskb8J@Yopt~Qw6B4Yj@fUE6erNagpTZ z?s#|XRB)BoaWIe{L?@E(;xI10RY^%apMbL_`)y! z(l7ndAN|o^{Ka1!{pZFDJOp4esG{Kp5JVa!JbK!F`n@FkTkY24T@7%QLjS({uTJr7 zgy0+T)~6<~0M;thlu+TlK_oItHg`r+jyZ1y0?rvgq&x;dt1HTr!#e~{Mb}e8Hm0LN zlJYpos-g(a0wSeU6}vz<1mv7?898SOQbN%hqco3XbGi5Aj3Y*BMLHA!31Kk+5Gnz{ zn=%mL4Jua)!LPg2U-o>3r@^wBJ2AJM1n{ulOk$UCYwKTw&=YllrbJt zCJDing)U`rRZhT6Lhwk~No`|{5<(e-;DQpOMJUs%4iKo2k&s54q}5N-mXHz&eN;SR zjC*gLvsx>=uVQnc<|WbFfcNSsckJMV0l;b{6+60fK6 z5<;MqIHLoSX;n+X8Rv!Ac2J~(5+U;Gq`LFuEGFkASx$78B#r9unRp>%5dcV;5v2h^ z2+Al0fOm&Qx(rEsob-{f(GUN~Cw7MeDn)m>XKYavyZLlWPb&cM)~a#ka)RV}ecMj) z{ezV9FaPo{Kj^dA!)HG8nORoAU;Wiz%^l__Vb&vI;4LueeDL#}hQFssGe8)P$IxAD zzwaj0Q#=pc361d3c)o@Jh}u|dT{}zOc>BSP3yV%qNcz;*K&A`28j1MnCyWt9v~>Xx zSRiPPh0yNy#)BOsj7ed%HpU_bKx~<`Hd7!}2pK|9bxkS6k{|d~BKWgH6^;xPi*1ES ztML;Nw3Ho7qbSOvM>2>ovBPWqHAZD`y#V=Q9G|C@Rb_#MQc4NIh=NusAoj`i3MSqt zB=qX#i(5N`bz}PJUY1E!lPKu|fY@IfEwIHcm;gW;%W+SSJj{q^7f{og;(Uirp1zVSDI^EW^FlRx=WKlM|y!vca~ zgj??bJbI&zwU*>#Dq~kZwVZk1b89^^!TY84g~tOE0zGYe`F=o6=8I+lK$P_AVmC?` zjCGL|0C0JIg$WUKWlc#A@&F+m(O@*zgVj{V&a@rnln|oTcy~MN^y;eA+K><^rOufU z0D|)YFgWKd2JejWJ`N!qu|ab{C<0|M0B{kHH#Z66SubG`3&bPf`PQ{oq-DgO+>5zb zHO2(*8Kc&Dpu!m4>GsRA@Wyzp31!}CLO6J6r|~!6y!)9SeTf7M03ynq)w3oSEyK5H zpvcx_f1H;9UsMdONAGm{YwOp}nc7Pl6E1*Y0Pd`c;+~q$QNuaK2ZC$Y zuKmFu{6RCZ0>JItx1T-!`-@H_s{a%nt#;yAlbRPKNFNnl`4JE?-`F(fb16&XfB~ zgeMRJBC$SjN*N%4XN*n8LnI6-34ol%b?MN1AAFLv78e%&@te1P><6zv2!t@L^Mkq7 zJ0oa(R<-)^8bo-9ZYpO0fKryGEkr~lLD|)nGvEHstEuFR?Io?tz#V161kJPF)QoI6 z&9{EQ_}bUL_UC{8=b!xKC%fG)0OWc8o$q|-8PnPK8&b+&`?X*D%2&SfJHPWgzwisc z@SfuXfMpa|Oq>hHG@+hrW^@Wh4<-OQ>au2H1%Oy!bxeNv6#pVf`kBh-tKtFxWpXqc z8tdXn%-SWyQc^C9(L*LOksNZR^&wcLWtJhK&avTe&v3??r>>rx85)`f!DeVgK^8>O$a0ybW=TR;^5U52m!O{-H7uivnuO@9QL?}c zCNBL%(S;fa(gMoZ(9qCL&t3C)=4aT`{rxyq)z#J2Og2{Med}8Nqw6{QsdJyRciqq4 z_i$a7Fz)%zVVcI)8kHtmtEg77#u#H56G~YMCNH8QZ)h<-EDknuag?o%y4|C0ca4lu z#xj|lQcBT1wHMI@TE=e&WERaI+uPg!;xGPUX-xuv*T4Stx7>2eU3cB} z@;A|LF|xfEl|_kBCyo$cf)xAnDy{$=#cv&WG>Togn6~yZeiIM|x}m-7BAPc%a2bM) zQ^i7mUP1;PXFO9}kv67fke{ytYb^q$O>u!H2QOn(rLph(O6#Uv6(E{40iXcH8bb+D zNy4~j&aM{(Ns=&@&Ik}3y>bZ93>H*cB7|_^5hDmX0PuX69Fw^$Q`!j5!({J#^sy)3uyw1D0D#69l=TNHVr&s1$YuOC zap8p*u3o*mwY7CFCUBB~G4_#h-IvEJ|Z}*S{J0TlVRRjgJ7+-gn)Axgc)bG7X$#5G1{nArROzj zHR*Y=M&jieDu)6P90DasfOnC#ytXUT-U|Rg1!dGKYHU)E#smMHBuO|IN+oF$N$EL< z3|OsF@}viZ7>iP%l-Q_7Xd6_vmKswiL{avx>|b$saPYzH`!}A_oeO>G9ak4U$NeNu zrs|W~wqlaRynj12X3wlq`s&83OZ&@{(HfL@rY*i8Rz!ygj54K^vxIU%DKkc)vyNpf z2up;81^`$`Bw-z7Js;aGi#;~Gs%eI*H4wG76IQiw#;t3f{uq-2C>4yPX-p`$2pkXq zkU*pEz*<0urj~E-ch030xzhbzT?dEluXYSi zfT5wGFMa7t3;1F#yX>;dF1ze_w=m9fP3;e(fDosT1ezB5Rw~Hx9_KR1Tb;0@%O_j1 zY-l81_N^xzeu2f)ChRz7f|#H(%Z+v@`d8$gNx2N>4SQf@?yb{n1gK`5mM;8-&nYgA-)E;n;_ zA;18D5a{KnyV0k>#5TK@%o6%h#^SW>$q8(%cK|`)CrQGEbk-Q9H2@$8!O|qMK>RRk zR3N-KP7+Q$WHy`80L3UudEnKi20L2wgRo8 z)Ke#kZ|&>rV~j1@FEAfCufLq?82l^%0G9wTqoV}?ue1hhK?x23FbaNF)=E*Xg z$yqX3$gefV1euIc5kc#RMJ@$e=Lgw(r6b=uSTDCEjN}0tjXGu2_k3$Dx8u z#{@QQ+SF(?GMUVaj3INfPeu{{xN)ji=36O~h?bCrTi4;kkj*dmX`Ns+5Bu6Asi{kz zkvsqZqhi7(7k;9Y6dYzb|8?4EGG|jT&6!`{+Fy!m87^&OtlBw}4yBaB3zE1&7)R#_WgPq!^vv<0=S$V$ zj?>=Y`$y%4j4e~q;;aV%gfbumbYj6Hgh=V9Y0_MtjIprLqSM$|2b6N+gVBU%w053n z8kM1zmY#g3moe&jey1NwA+;J2oY^!5-~cu!WP5RKoK%d_M}Kt)#lS_ShAI_v{U+5O z4{K8{TbX3pA|L_*bjwvPOOMyR?sY%?=}(v1iX(W}yWaJ(#yJbtfbamoS_=sCS+SdV zg}MWbtE9f*qF}@?%IWd?bZNP$<%GdlRclPt$e|iLM6yZ52TQoSuEv3KN@$d%p+7Is zj*f9TL!pbVDQ#Vp;l;hDUA%H*XV)4=(u2?#l0l;;gwTW#z`!BRh{*S4iS0CE#2J>(jC%qK)O4n^U&Shp`fHla{y_O{?bYaNW;7Nz0aSA3$D1>d+oXA z8sjs^a)-If>EvKLB5=(Rko0HmD-K1@<5(L*WIcHyLym_Z3@HYN@C6@2niahs)6vNx zHN&WH;4>`4gdu%`1w)B$Oo%1Qv-sEorSTdN$9kUf1Uf_Iv8tI2E*buq-O5__-*n%F zYlUk@p+$_*7f3VAu^f6Dc~ZsVr;TiTZ~A&PFe&d1K zx%c<;(jdZ6%DG%gk`AURAd^>6KtVzhQ?hFszKG^Z9(<%#*tHc!2Gv~caPr@dVaQl1 z$qcno*CD?}P)Vf;kaPF>QLV{FsM{b=%l!@K(=w%z(Pf79H%%FjIx0*&9G@DcF~V`mtlbeQD(?K;#YH*TgHdC|Ae8 z!|EkG$+|aFhw~_9rWBdkx-yi>(uRx75SPyDz=YFK$d-A%kFo1EmWa)f-!Xh!?51|t z!>xPhQ`G#~mq&?Qq_N`bY9l=i9{atU6ShJ~1E0F8g%emO?Zz)vcAecs~ zWZ)$85?I!Yt>^rS#dJ4~j@d`=-x3%^SE_anzF!r;>Bk~Xkn{Kd3U%}I>zc94a~&e# zU-OtPVZ9vpnZKDy3i9~=nqTDZpcHUfw$2Rv*IH=emeZdZm3%>jWyzXmLK}4!8^}`b z*l<5hYOO7O=R1{VFuHT(#<>s!ry3q+CiTb#l8h7&ezbNnAjWS_;Lbg@z++3xt-HR*LJ;>&TUxW|a#q zEC;A5VFIb8BOOxkzjptf`iljxWS8xD=AouhR>BPDkcp8ZpuV59yI0dlI8qQwQuS|& zV`zpV)$pXE6$#4KxprtAh<_qyF8_0BpJ6IzRn)-za+|_9-Ki5kN4NXpr_z7ZnXY)?KH?+a@uLCK-Bw}>+nm53+kdDHEyr1zoFsB z{fLQ)*?ayJ6=fDT&oB20zY(2^-li9x{^bncmhlt_SRX4XYc z2d5rg3g_eBNFf2uuYnRJMZX~D4N}53YnP=HH6KbcXA zYFb;^7wzSMFPew?&4;*&iaDPbTt;4%NQ6Msa&RyxOW07X77ny4Ut20Fh$>-eRfIbd zBmcysu*7HG`!A&_#dYpziK#3LLF~7q^Tk$OZMdU@uysAtWGxReKxswW!t&j~Uf+o5 zDLHW!VsoL6Qow< z*ceKx;z?1PG-mm+EfUu7Xwu{Jjfc&Brb`#ma|VivWR|jdLO5U)CdjL;e=k$QzjptF zhqK5(IzCwc+&xK1nBqNd#r1j3YxRL;*X=fjp&(iF<4Rj~XL;9V7&_aR&9DuRuuM*L zsSyV8+tJZc#UXucMCGr}-4`(7#;+$`Pft%si-kVhG5#l=`#F$??BJOTQ9z(t}`@s8Vud%$0|!jGWeP4 z36c5<`(i5_xFTX!i9os?6Vtqv@_lScla5ViJIbQD8o5(6+Tmx4-1&4_!C%__c(-i( zJ6G%TK9BlhRy+#p5{*e)_Y_{GVP5i}WEFAr?#%NB_i$r~-m@Py*G}^vR7SuKkIt(y zlt}$rd8XO@?lAO@3ZRTomvR!tWR-tg-zF7Ju-q=XRpWWfE&Q;)_o^IfV^FJ&ME3;; zgXsqLz7r;q@8~1lka7q?8b|gMWH%HC~gNFg%c4VV}bc zRB?`>E$5IlRUOaZyL`K;L!ZUzw#yG$=rYXLU<9jnkjt9qqSHptWB;qS-|miTPr-(M z@#DaAqinlj_hCiu(UqUF^7ybgc&k%^|3}mW-;MkA#f=SdE-tt0HSg!MPvQaK5i@6T zO8of&DKQD)llaZ7tPxh`D93wp;>^iX(K~MW zc(39@_E`c=j;&C^pL?uXuQ0j3p##a5qHpNPAy+vwUENO8Gc}p0@d+2%iEhU5_xGOnmg|}!^r&OcTfqIVekZ7ux#oVTb~cFP;v1aD$Bck9 z+@onYiDi|J_WB&s0JV&_$4>qxrF;diS7d%|Z_BC~e*gX*3RiAF{VQ=W?xd!Whq!R5JLV}k=Ff=No@0)BmM>K3vc-TTefBI zzSLAY1or@5A)&i+_CR}cACt-~IY5FK;RFtVYg%CYAnRklvGPm8xAmLSaIJB%JFmpJ zfNPeS(l@E0SzV>_ZcD@oTV#aM7>e4XNaJG7cZw_HOUsJJc)#>;Afs`(q9~X^UuupN zHR_NePq{s$!vyR1PYooXdmy$tW=o|(oh)m+t8BseaH{lIfwc5j_{xmm2&?-ueCcy# zg|9+dS73p5H&3Fw`)S5`w5a9ZR4*lz=pW2a;x#yDaw2~yiSTNQk>82A?9tI*eJR}} z52H4D*ZrdjFJuo04O7D3PsNjvilJ3Ft3GF-C7L@=?|j`H6YgSal+(&V=1u6C#rcB&TEjKiyqv$V>Ez~9@K~m>*?SH~26`z9z8|m< zgeSlKp7AMRr4)VsqZI_?AQ8ROZ>5{i19LqVq*bj9ta_MS9Ymm?!tWHoKGWL zM{qz<*NM-vAV!=i{x>B_A2Pn{cG39Q7m6_N;JMsf;NrN}b@h_#56UPL#1IJN zevm<|IbulUVuCx<)bH?tC6~|1?`G>05r&phdG+6Yf-FmID)Z2hvmZQda8&jx40eTh zXu#Bt(}lY(K>7G!j6ThI%{Gjr#!&^lp>jq$p!SNi)2q*F`6+0ppK95lV;I)p;QOPA z)txFlmip@OoHkL&u;phQ?mcu$SVt;99g|n$Kdl@rcl(y^c&D{&iux`q^LUAxk>z_NrgbD`7V~1_SU$wNx<3i^y#l$;ay=INY3OWma*$8vjFDs;q zU%KS($3M<*Nl90FgP;F=-gqLL+~rCP2azvvQwKbo%{;OjYC96wEw17FF|%~CpKRN^~ULKqG@8FSBJ7~RQ~N^n9o zR>j4bk0TIb%N6>esJq2HG|8$RuJl(tiGvz)EnZ9)3pr&t@~++Go=epqsgdAQ4gOr_ z&k8RPsGVo`()XH+P(Z3k4J{+yGHVi)do7AahLhVjp<#(-wrcJFXqcKpf6TLrL#49l!eG?Ku@}=N;aLBHWApg92gz)yJ z?|$R?iOAH)+|F)9aB+6leJ|U#=ZM63=ovrH@2DEwy{<9I1vs9!Gu{~yV$kTiXO?tq zlAkAzm$pok!8C##vFjs0oG-ny9x&iGd*`+H&MfhE+^1Xu2pQF!6vPPlw4gMFBL&AP zuL|QY(q|F>salvD_`4k~nw1$E)v%pmB~To~9Z3c6VN6d9geZ=2kn|qnj3oxC@spxs{-LqNsz=eg+Sh}V82Mf)9~8J1 zJ5Eweh`w(j!HY`wTK0olvlJso2j%r8X$8AgxJeOM08ei2~mq$#&fG-n=`?c zW#Ako8+ky1qHH}2&o55{k+lszHkaqI*&-iD1|nVQ6^GJT zq8>j8^suGWL_sa;z33Hxb{F07&CShsEb)NHtHt1p+znR3IR0NQ-!+XqG%Y7{c;DVH z4TFh}$>>am@$f+Y5J%GD_7~wvDRmLk6{Wk*GR{A?hD3p$Bn*TiMSMu0%gT!9qoFb* z$kiKhaZ{X?+!<08!B;9|=jrg16i=*pqAH6k6mPXt*&|5wba?=9abvGO#p$30C#;dh&*TcR1z4SJJ(i2+ce0H>)HH|)-fRkX z6QMGzK?Ga557s%a%5+oA12CfecaL!H;nmwbisubF~VU#7dTMI zo-JE8Xh2kHpNL8$0BjAxQ4JOo&Vh%Y&2@s?SvAzD>fPU{eMF?S_9^LGlT-#DBaHDuGk}>#ZToTfyWYF~+{;HvaDV zm-|#K0ZUX=)X?y-u&{9EN>${SokZb+fWL}B(}JnTjO?lJlz+x_*8OSkGgx8y*L`+g z`Y^Xn*+5fL*30V5@~|lg_IcP2p;xTJsZ-ynYzg^WkgP@tX5p%lfG|_D7@h)!ypV5q8eBDegIrKg%8-sWQfcYgkL>Aa5Q*q?atU@i9LB7>X8XeeSilqZ5by1P_L>T3&n;PF7*FNoIjL70gA8g zPbc2J_b*2L4~xzsdu?je<+Shsh_I2)o~U^jYb<0ud1Va?a8r~u!xK~oEDKhLJOA` zQ!3_q;FvQPfkCK}P0LzLQ8Zf)M&M!lEO_>cRiKz$5Pl`S9<=k>GO9Vs$z*=PVb9d3(7nk>Gj^Z zoe24!`S)J?+vohdytJ!-k=c}(%NKYp@d|0M>6|-tc|kRpY`!gqrWMx8SI2qW#VJ`t~Xa@{k7g`WQApy<@H(H6W0J zXi8X(!-XyqM@4<-rDF8523?TP8V26~_Uw#WSD+p(n*czaSeaf@=%jyErDOjci%3~~ zWll}hdi-9-HQ#=fv1JYTKsE~$?J(~S7)(Z-##2K}<2o~Sbbr`S2s(d!6xaeJP*nTx zRIsI1R#%Yd9)ECOCp!B(c&t`5yd%k2RTpvkgeO3 zjOyEo1nzj`6@-55WKP%qit(c>X3yBIaVL|F7VB|v``;D_IxJ=&`PhB6Kz|Xw*Y@7kQlfn9I;=Q6JZyytK~NKxK{aS9`02vvW9Kfo(CH$6ue8@{Ge5rI z6a%iza8l7kC2FJOakboiqFF?P!PPZPQj9x7_2}%ivkK(Bn;%FRu$8J+=yT_6sRKt+ zs1N|Y+SbUeqH{X3X}gXOU=R#>J%l{5PI7mT}YH8r_-Y z{6n%xDh|>w92l6o|A;G_ZmXPgXzfNZ+oh&LmKoyVQ;-0OSMdz4xbP4{JlqKFV?hKF z>v!s^Ow9NwY?KmkZwzg7-Rcb|^wm8X-c;eM()N&}h?Qt5MyX@PuXlJAlwZ>8g{}aK;1~Goe1k(e3oSm5c`RPV& z&*Y9ebiXMg$?=E9@PKQ0*c%V|L~iKxZ9{~5Pw(G>+0xZ?_pi(dPELPBMMaHAcxtXj z>xk<3vP3)&dQsDCI|}g507h8|(8m!5n|LP)NC2-%1>KIz-QRS>_;%Nl&-O4g1u(d` z;(zz?H8+Qwz!3|8*|K9_+{T=`Q{R_Ook3i4Z^;>=qFN_MntFi#1cLsl4S)!Ym zb*=O&PK-r3YtKP#42K}Endo+`GWxJ8l-fI_#7I6hJ&pvlN7mj4OtK1XzDu<$&j*90 za@uTa!|k00SuUmbJIyO54OFMqn?4q>b!jx85w+aHLT5|6axHX}9doK^Spv%^PsY3e z1sy+|Vc$Q-^aJ9KO6_)T*JnGG{|b7mFFaQnC~D{Eb@C#zG0wS)v^F(aoa$e5Q{ggh z=@;tr)_L;=i*rW#NhyuuKotet(D5xOQzg(g!>?krhFUlCkh7NIxnX-PuM9apx&|KK zYPFw_EDUP*Gq#qr+FH2W6+iZh?9?TYG*0X3KmRu6KDQZY67HZwRo zxZJRQ-T$;Z0(;{+vqR)SXA`{b=PTHF(bLn{wLANc8|_*7y{Eu<{n}}z?Jz~20uF$6 zF5J;M`~I2U*ysgm{}+TEU&=V>cGsxG(cBTo6>U3Y4)wo~5gvNB!D=r~Ewf*mBXagf{_uG4BmhvGR>FWgfSy;OIOfPBBDkK4 z)!b#aIBZ|R{q--d&?>T2c9W1fkLQ0Qr71Cy_2(DMlaLxYllOE0`Lh}2N#D_Z0 zH2M|M+uzG?_8TZW@&qSyhUwRqV%zpKp6fc?-_G_@Yj_SxqGNdupt^Bhe3_P6T+-$@ z;760LvS3C4P_!~RFbV6aDB*JM_mvMXS5fCBbUVL!^E{l#4&QHM&G_1t%A9fU|D7B{4aGcNmX;Epr9a) z1LrdJ2E4>D7t+}MFV7t&Iru*KZniSdZERGx`F`PZ&(-_q%lGXIPEJnZ4_jE`7ui#+ z#hg8-X5OGIY2ux~a90T$nc&P);jUY!_)WODezLix7>zHy4uI8{wk@D``6Hl~_wb=D z{j6o7Ol}yR82L&516RQk@72SU_CYIl(4soU!31191<-K&mxcjr+?Qro) zIGEu>79=p}z5!?e^X{Qv`!8HvWgo9eT`59}M{=RiYN{>cp-du2N+u!$_q zuQfapr4TMeqX-v%uA~~3#kYb$xN?~z?u||sBDqKrtTM#QbiTno5uj2PA};+PcN7+; z5wcV#Zj>f$c@@jeylW5ht=BYcZ+Q#UyKB^U)if?L68)Hu)9rEH7=-l?1r_-;rD_vu z5nl#AgG>8yu2Rf%Bk=lV(rMhL)zZ>(3e;b~$9Y|2;}%m41#e+@2OU1Q+uh95<<|Y* zty88BrHNttzAx$n*sWm?pF4eC%a|;{H~PHS2H~&%FSgo_9)HEFyaBj$o#4N%;^Ylj)-oN-&pp;Z=$zNi{<#bDziao5 zvkZ)TyU1|NI-8d6TGPgP>nI=~G{2S#Q5nkqm;I0=&sm?4y`qinHKZ{(@K5Dqib|y1 zcorZNHI|$`NmL9EFkaJUP8xIw$tk@RabYh`G<;vhF{zWMy8@S+jtp;W^S8KliU0PY zq99H>)5BW#b+zIjOb7=Z6GBOaNc& zwJy!CV(@Nug3=EruHWxExc{mAA$K4z;^{reJoQ~C0tbTL2zvz_NWb-aJT~hM!M_bA z4A=;MI3EVjACB?9U>z5`n@M78mqkA>e7-GwAvLjgOr=y*RbLiA0s_Kqz|&D}W6+Ce zVNtr@QjAQAWcy}f$J5}~XTyAQ_O>w)_YmpjfQ%OBH`E%&ZJ+_qmzU2U5AJqok_zTs z|EZEaFCrj3KVJPYGcnN@#Yx~EU?sIqFR~cEnPqW%WTU1QpV zrK7v|Z{;b^g86Rq?gL;pYPLtPrALuiOZ$~af8d9?A~_kh04b6Z zcR4(%P;8muh|j%#lyG#Nmlp4tKgPpR1@dXdARRb5)Cn9p8Yd|CoGwCM!;`cPVSk7x zDgA=N_aE#C!{3xql<0WqR}dZm)r?;H@0g`L+-aRuRXc(g++~y8$3yh9R=YIcYbqu1 z+O;7_y`iRLkZ~ZA@PUohUun*lsV~)a2nak~4!ISjn$0g&Qh1JE;yy0Eg zS2M^K-!;2&y>|kAOLti3+aLXt+!8GqaBO>w>L}RghV^Yu)n+l!TtZ4)=OUji%7cxO<#_irjgXzz2AfT|y6dJyZotp;V1Kc$y8)_ln&YQtusi*F z4pW@-&PR1#V9PRrv+z|kTf03Y7bNcZ$!*-s(^_r43CI-NF@5zZ)NPP%9|kgm{Td^L z$?7ZO)VqLd?0 zqYwm0R*yYk#B1jvwIjEaBbYT7Z7-*vx=i`6MOSR}hm7lg8A~>LwMaA(2AfT~-*2KhO`{H9OB%cPMhR2kUY?!`{5PK$&!Pxyj|k36ULQq&X6}kY^)0Rs3G|x) zQ%M}?|JDD>aTaE^N1B!Gxhp+S^!~Qn)(AeD?a87mQ6TkLk4Q4@mE|;b-wgIoSu~?bX#iaNc zk0)jIr`=+prgp^=^l!!P4$x=6@_U<2lXyMC?v4d_3I9|E-^Q4cKRNIJ>IgNvneaZ) z%taRQu&cF43bE5BO!&aXDYOX(U-z!T-^)$jXd3ojS94HdYC_#?-QUK}&ok6D8x@|t z{{7NV(~me01m^cj03&g!BIj^UzX2+s%iylzrdGwRYp}mPCRY1z{u93!V!k9%@kH6{ z6KkN)V7G2h<)q|wq!$Wtx#-^th0pzmbsE+VoAS@de-u}iJz**{(r#nKmR{rDU!|e_L1~-7u%q0F4U;xR_tD# zZFRlXucg<+V;RO7Lxc}TdbE5pC&zhJI;wY_lKAOa=%)4cyGo4tSK^Q3Nk(nest6P! z;#bC|dxiM{{{n5F`%V0NdINvQNJNC80t${6`Q{OVZSh=)j&22917tNPu2V(n+F}At ze|o~7cd<9x?vC&vXE9QOE;k`W}?PP#JSXk?ea3TmEr_XaE6%DB3i=d0||I@`Mn7v zc!nlY%9Z{A(|%OMvWy5jA?Sd9zG!{p7kZr<(%KliWOWKH84veS9y7O6OF)h(U9*E| zQDq)Ew3)uTC|C332vrG{3ct@_zfBW%U|cMqk&hO!ZzrMo<0)wYTVfDw zgS|m520V#5UyOl9nHt|P8US{sPxrb=Q|^U4k4V76iKyj7wnKZLvvl1pW4^Pd)G&BW~kA^*9=r>W!BlVT?jR9;t@ z8ZEU@Ph9i7x{)PSU1|!4llZIvQ3FDFnW*B`kMd+owMtoqhV-)pajkRJ=qu9{0ZRK{ zrpB$!mUwWQi|yU%MA#`LmP~MCdG3bx`*~1JyI0XlT+<$WEV6ksLnSE7TY(7X#B-tr z3)kU9y4s^z+7pX<`zkD;Y)}dPkrlJjF^n4|3S4i8*MDBu- z-Z33*4S~x7UiF+dntc{aEM3eG%JCY4Z-#2HVZU)FOmetFC3pXTfQv$4MdFBLa7g=!<2n$sz^ z*j4YP?trF#z%%HG#F;&8J30HWzPQZb0ASDVJ7)taf0*zoc=i!yS4@4`bE|;IsZq zyGzuO&s=?G@1t}g!^^s(wX=Gi{;z?#Zk_k>mkE2olz>y7q>Q9&9gUNxRY_EXGQC#X zo)rbqrch3b1uatsu3*W;f5kN3-%3o zC<9#xafVA%EH^&S*y%&Elh>Yd+=bcEWZCLf=1ALbZ6%al@say$Oj|)Wa41GMpye5u!y+Gws$@ZfoaB5RHS~qPj*yIc4Syg*{-5lrr`@ zaUf<`pP(QAYW(`~H2C?x-}TI4-+lD#W+y3l3*8JHU8!zs)6^dRK9oQf49X}xWViBi za*6Xh2Dmpp&o4ski{*6B2poe+r5>@QU`AYx-@y1g>ud*19Z zn_on_-oDu1_Y>lhAML6tBiu`JK~WroE288=S|rNWoARj6vxrDf`w1JhWjk8?+s^Pz z^)ms~EF#p^h^e61>S|Oa!y==iGMQOryms7bi#jG;?3OJaoCSvZ5w?9$=a~`zB*VTvseGGR9AqqmRmiR1}8Ah0^pexULl`5W5T3;MM2Se@FR zJg6LbO7}V~NeX=GqDz@(qVoO%*(x$AOddAvsx5ucR^Q%M@vmFiRfDJq5F0gN6-oP{wQq>~7g@T7Cqih(CaZG=uWwogM*4hZZ}ufm^y(R7U*x3Sjl zdxuInl@5*uaux@g;U%I8(U1Q|ejHlbJiwRW!}CG8aon9gjC`taMgnk>?SA^b>sYqp z-Pfnd6%*_7XDzt2`D{2rMUUfGj1!-QA9?D_-CI^d&6;fiF}LW-VB8&-9Y{9him@76 ztwGrXI~y#l{R?0Clez`1LY7=wG40GU`~)&3%uGzarj!+uyQ;jALNa6Qo1S(>J)6iy zhHI76#OCz?0v&jj5S;}J{7mJ7$-{*Zn|h?Fi@&!I|4mcbrYOAk>-jjBtR7AC0V5xQ z%HfKXx96r2>34qtZ$Slp($_Ei@UZauc}?Z% ze{j^gweuC;#N_1PK&}l$ie;xCYF-o%_I4@`LBU&)5vTTDZ%K6l-T2viEP^D z{#uo<;(T`s&K=&*(@#zay~GVzzWdMBEkb;*x>lBW4D=ZjT6{=A(k)@aaKMhEt_>cZ zQCnVYiCJBZ18+TLiR7wB%L0iSQZX%OOc5>|u{k~pCE+(IhgnU{ryGRlsq2R4t?@Q) zu9;pD|Ka|zr}z-vgmEp3@|0-9J;BM;{jSMY}Crx9%?U%uUDixZ-^wD_w?L7P7C+zdl(cv}DPhWEy z68WNZ_ZKZ$~hDDlC9VM=(Qa)NA<2NfBTfT1v1%-FsgJv z@PeW4itQb)h_{3v;04(Kb2C;damYq4(v$ggYhgrF!;ld5Hfmvo<5H34Xr!GK!uUmL z`^fJ+S&e(!i@L(~@Vpo+@Ib5Z4$2vY?FPadZ_)?c)(%E|?XPt1bPI2VYo|`~eD>lyxC;xGo~|mNTu(32hYsf|pxD3wYHNg`M_!AZ zA(m{E7U7|SdSZ07DsHZ!ZMu$Nww~I&PCo7!N_hkab02Qu{TMUA@c}U{C6U!|^gkaS zuhZhfUe|dY_F>qm$aSN)n7e=OMngUqO#A29?9O{p?q*9>*FR*sJ?Ha*|91KfcIsla z@}~$$HJAgjfI2#3L|Aqi=R2$DXk%pU>9#1-M9MzAS^uaV-+9sq_z(^?R5U|8YS4Nw zZjVNU78SH$#^6p+!NUtF+ZbWRb295piYx^@qHbF&7{3}zpZWCDgk}^@LZsa1Bl6w5 zyAQ8XTtecMv=ZgM*IpbCm896py_IC6AbXTe@&49u{rc;$cYJOCEsX}9RsgGZ51y1l zlDY%*FTzH7jG`8Mre1}V$lDU3Ndg=bXoas5dGz!p?r_9@xqTk4Y`*8obLB}l0xe7J z<(B)phjck?Ee+xOL>~%kxRp9;SV=T4E%OmG%5e({OO^{ZlEE?^N?6wop1w6*T^KDA zqKt0pf1&2^D!&V0CMJjL_d};it0uGDvukNC-o5*c4M$+8M@^UK(YJk(eP3fOEee2= zEJ7)qubKN8(!nF?7}y9(BCBFYhllpg&d<4GI}3L9_P0;hy}hnrM7a0HV{qpB6sraKw3W%WG6d1Q4$;;YdL@vi1s20XSY ze$u)%H=4flM^)O@bPMxWXX!JF4%Mn&p)6f`$71p@kvpE3gGKki20xeZF=oC`P!>CAfarH+tUUY%Cc|Nle!nGPLBC{HrvjY)NEf z8{B(W4Eq}ulh~mOt(A`8q91VN!vZX{^Prq>0TlC~iWs-Tm?GUHYcZMc(y#%uyA4CV zqxJ2wgdBKAzH)wyH`>7pzWHvQX_Ap)?A&!o4|(noXAq7c z`}k$+|HIDcnBos-mq|2s%{OOQ&a(`L3j{e5!MvmMJaw)=NU*mdHv zv>mXgQFi7NZ?~41lcWA~E!7?LC?u0XD^MQzBzY?CVyU-yqyu5OEwHP>N4@r43K_we z+(#Q(5C3yE@lcly>W17Key%(2_Fy<4&?hLLf^x)E%BcBjK>#5HEDSub8>l@b;E0Z% zQ#aGI8odAFSl_7LaR6mrmxTt2;Lw~~1X5QV5h;RqoYP@rX}v@69JuU_`M6G7dF{;p zFn+50l!3FCr;J5Vje^7YQ(?Zq_+c^E@x(^W8Kh#g;~5!Tp>qnB9px0r@oGabYBGY#z#jv16$A+3qCY|h6=}07 zlu`OH^ljg$15G2_c3JxuY>$N+5`sh)jhxSO4q|k2bP?*fdnLtc8TRz;H8c@gW1_+TeyxeX>fIH! zQMs}mI<4{vqF)=p1auClfUp^ux(gg$Pj1uto$1!gAi?c^Ver+w9@yADDrd62B(-!s zCaqELui3wVlb{c>1{!*B06Gzyafjn_iENzLW78?>(_!HgDo_AYZE0#khv9D@C;`y5 zQk4n0FYE_F`Xvy4TXp)JK5h+hx|_FicJ95|j^od@b;o2>ZVUjRfCS)6be*d1ev2@>ApS7KIaB_OXOenmuTy+tcgF(@K{jG|yk?a7=fa)!u zkA-d62%-Mcw_$Fw0Cq2&`Bp1JVX-NGu{BV5c=BWtTa=1D zym;=0I*PTwc=80Cb_rxOUb1z{*xLf<-)1rxOXf8ZsHao7!rT#~TNJIL;HOxoBX?Iw z|I=PJugS_>ey2HJrmAve6nPLYMGq9MTdEqjxgEToyG&k|zsBHeXDdLk ztUJ-VA7g1G_n4Oa>eF{k{`mO#<_*p4enfJ8!t>Lone}xsFJ$ik{he*JxmGTY@$!0kUt?qr5Ea$} zO_Ws~sv6Kt3;BD<*Z(5z^9(q@sqn2Y;(Rh_z@kKAlsK5*&NeK zt(Q@rQKXX-f%h?gzEp|_ktt*+f_tEjJDvk^B2FYkStT_CVb(likao&j^y`mo^)eti z>*h1d({WGw^Ss`1I}Eps;sTf!%H`@JU;4&KTnnlBckneyofc3d6=V_j|7iX>KZu1Z zNV;H(hq+dxEX^K%^352Pw$5_ZNHz$A5$~XsNN3Fb96+Y3O4!PSSh~Mf zh10-?6x7>oyXqnByBSoGF5nY7aM|GLA({GYMS{DC`FxE|v;vCY-w_)2u7i?M)uUq{ zu&$hfT;bg$*f2c50CHcw-T`F`I%yw#d~RNtx0gwSm&6M^f+sH&keuC0*E7BSJI-F{ zz3waj#&hmj(&;yt1&Bvv;xQABCB_)B1d=d1dL~!BfpV*G19C%%b&5#q)9AxBIOR*s z9k?B~^q;{_Mn~*Zlc@AxccON_j!cK||b08^T%5^jSuYG>V0l@GbnZ;N%a8fmFvyQN@1zZG3dT!I-2D%oq zqf;YqKLrPE7jlWXU;efXe)#)3Mvd5f$RNxvKSfS!fLL?ic;vf7`qE6@Td(E2F z%%33NsAx?|&E;(hfe_qcI6yH+96qF!_OW?4LSHUL032JH<*Ieh!2!+?-nP}fe{TfI z@1P85i<)&g{r9**Ok70kY=Q--N8CmtDaQpt`h>C!49FGphx}sa-hY@lmZgelZPB~B z#Jq%2q3{1kgqs8}Q88Us?g4Cm8Y2K z+s}Y~s$B-d^#^-5r7Ty*sB8bw*>?9|TwM+e?Cb`9q>02RO!5DRS0_ zz@l3x@ceM$?OG;<;ySC!U+#bQ9Byj5BMl#dK)aczMjfYuf@u`EJM3GE^T9^l?)u8? zUXRfI>*Uq%yoHLKkNH2lig29*F6xQ64SpZy^OZYM?X%@h!t%gW!py<1kJn~TXiYYi z@4syFl8c|FA!t0CIIm@2{Ecr?SahS_*yP1ev*-)kD-vAbq}Ck6%`Z#S<28|`%!_Ve z)hY{fVRjoE$s6Gu5Z!YhcvT8#U0yU`keNmMotw_!Z*}HRRN~^FRsQQewY>|^SaIxM z{{4UmjpsMVWWHvl3CTlK%i{Sdu+!QnIGpS@##Fqpj4`EcP4^#(Qq@AuCNI>AY1sXf zns7kn#wVe+QbT!72C_qoMIAe};% zgH4{livB2n9oY%%{MNfjE=M|JwfbN!yPQ!N7s3)dKJ>3Te?cP^BqkHY>?0Sei2+pg z!&LA4%pPZ0KQxtAjmw-dZIG&n4-FsU;J#otG(CQcnB9JG8>94%l4XY(_sH@0ZvjUn zT0;1;n9_iU&Ab0`_PsZZ(v)Xs)hEwskZhQoE~|YuoZI$ z7v>AZu$qoQYMH@m(BgM>w70iMz@qyyUJTOJw%)rTUlT#>`aQkS*{yiqZs=v+*P`-i!pg@8?4gGAX=RvRHz}fJ zpo)2)TxOd21`(O*yHEd32xtGgn@;9m-vL8njrMr=ojWBFm=Qw9#MOda=0bJKtpr$F zP^#*1wY9Ayadoxkp{}yYVUaQnh)i%f2Qn)Wl+`s#QMS-@%sNk?uda30oqL7*Pvu%L zwWLKJy+mFs#gxA7tCAUbwhf<{$nG{4;7uat1fQx1u?7wa)Rh`_23OCKW zz1hrPUcVZ>&g-kRAJV z^q^T(YU%{@S^FTH3kGxivQ&_FkhVWXWBQ`84Ru#c)rUOxeTLzpXPiU73`1ws!b&B` z6FzbNUMjVB&9KQlrg$HLA_h#1;y<`$TJn*#{odI2)Y;DN6qIi7PiTj!K9USoFYM&v z;2;B-taeRv-#SlZv*03)ORaxeMRB{jml3q@1Uy&^%7nO7p5rstd_>~k3SqGoY& zOF)D(7ce1f>ggac9DaOv!BaXXKpMX5=6f_(ZL}dCcz3ztBZidr;qLOVvG>W3`Mx(_ z9}KbD{t*ZFA(!vf3(o@neSdccie=*Yo(l$e*%)44UZx;5v>FV*I=IpfNdm3iVG94> zP%X7=Fe9SjK34p4TKYvm-SFMdp9=cd`eJBpNWq$0ThlaG*4KMP5!&_40tNOK!v&Q@1dtKpYPfba`7aKm4cIRz3zwC?g43ALLVwvvs*g) zX9Ic7<&$>nUJu^9JxjCzH?v2L-VUKnNsH9j8i!gGT*zx06@zrV&VC=t@7%uZQ!y?u zLzji@x)E8SZD{4!n>KCYvkw9!A2D)p--LTLD>9ll#~=_63T4nYe|WQ`$rZ5JB22Os z&tX|tq+(EA$2_j7yyTEyU&SR$uWC{EFIz8#0JzMmti#Yh;B;oBxU4qQ;+3cy8|yIJ z@7VMmpmuH9h~DGzx2CSERUvspRv&^CMig%%(ah4^=xv!T2rpwN*Jm(dPZWv(iB}c3 zm-@mRr7l!LkgOf5F7JaY>pLbd;0xn~Sy9J$BF9^c0SZiD%mD%h09ebA3hnJ)J6;)u z+R=YwEljQA{ljxAn}V#tl&=4c`53ONqDTMta*N*7o$3RJ3_fC$nurTqjcmcGQwenl zi*z&9Z$_-^MiOJ!=}T$Rs=B5%>zTDBkzAct`WnMyFh>mdA~6tJRG&e69nDbJuHe*s zCuhdC^u|Vu68HCNO)w#giskaje@=8LwmTlAX|&n@kEW{(s;X<-hwko_?(Qz>Za8#E zcMC{Lmvnat2m;a}CH2rPt+b?sh*Ey*yfYua90xtj?9ILIb)~YLuabsta8OX+byj22 zGy%ASU;Ovt8n*8MOLv{ehDYa4j91QQaKM4by()`B^$X_0j3Utd1K{{)n4@wti<6V{ z<;$1J$v@YAeaBOxg!wdiRMJ~!rT!;{XCP<=XpDD*VF91r1dLb%hu)j-2rozjpjEnS z;4Kmp7gwuV2z@vY`1iCSKHehv2gdP?)4x;C<5O_i`u6Qb%nnQ>1PB3*>(s`ur_&n% z_`hMBg`z;Q@ns;ih>?^c7@3he%1jq_ZpoN9|5DZj+Xg!-T*b%i714`TkM}hq*cg-W zmFA;2S^7Rm+pxYN_I)L0Nb=1fe1%N5lZGgp z-XRg|if%ZI@h`>B9kY)+oumaU2d&NysOfcebXMd1@hT7*Qw21}xU`f-RP6A0&6l3? zsl#H#`i>vStg+23_N%fm$s8o8S{ap-_|uZW=NbwBR`}d7s5w*l{+AYfwn&CsF1)S0 zbzzI*h%#weB%d_Abu!&JVo_F2fGPZskF;%0I0=wDDplR;&{3sy_ZzhMIxavm(HzLc z`E;(Ck=ZSs&|sSBdkx0ra>HLc6On^P+g8GqS!@zjwQQVzmo$d<(rGaqD=y+Va-Ow3 zF18>kl^Wq?oL~WbI(uUKM()P7UmQ;OY5oZHvJl@D1wk4_G&lx3lfsl9gV$k*2R6Fy zjQ&goh7r#FrsvVo9Bu&#YYenW@Z~SZl8_j5N0N9Q&YMm$r4%^7cKe;bQO&92+-)G7 zqb(9YdNLm|NKa`@{_K0a08)DYZQeg`Z*NoGU0*KPj5R33j02Q7@2OxUp@$xtRu}@itRfgcys=bR_Ay11VNi=k)Ox(^12{Lf#}@ zexV*l?QU_<2)I3rS&%YYT;)HNW2fSs9jY*z0j z#EXwdDWb|kSMA32?(cWAN_tfm#woGH?{u8ve0njvv?abmw)x z=WkpE*P+v->|fKFaO&Iqrp@I@d6bz2IlO7$OgJmbbDW6Z{H~YN3h*1iMTeL{N6`3o z_;~ek^A+vPY8;X^MU9;#w--%NxwC3Dcj~=Vk`e#5CMwkvDZBQS!pTf3dQ4d8VTXP` zjh;b8r*-7V_a)vBuocSK=^l2hc0-2XLQv*Lo21)YZhXYqPwQK1r7*m43MrggbctUr zaAqO#>DGIGkFlmHaU%PO<(Iu8)WJQGZ$li(5#v(If1Ma8w)HkrBV8u0Mt4DWlo13C zoU8reesZ+x%YSq>+Hb}iK{&f zlPb9j2?Np_wQP>HLy<71j5TWe(^#orWx%k^rjmXNPD&sM&y#2S2NP`wQI_~q0(NoO z)Z=s3Gnh6dx_TXoV4e{wBqt|>7iX6zclM~U>yRAs2Sh9jH{6QoxH?>oaEE%GO#^&E z0`rTWrl?&34$KD)(j_o)>qVo`H#fW+#ec|2k{*BsGK|*61qs^%5~5sXTZ>5Qr?3vTd;OSv;6I z^8-kb(o1uuW&{P@agh&+2i{D2r11@zaN+CsJ+7PwaLt-}uSVf$=$Oaz7BJSaG2yQb zzhT(bAZ4lv%Am>)i~bEfQ&l_@-wO(Rr*n5;kb(biQYbPW`l#wejD!FZq-)9 z^!5`|TO)e^z216lqp046t1W;h|B44=N8i=5DmYj@KvUm;uVvR{iXz_*KZ9pXlH2A$ zwi_R!xNm}o*akmGOBMBMpqHp;+TL|^=%)8hweq&Qz#W!kw9uEmau56z>-MhZJ^tsw z+AiU97-x7SFBp->?_lA#Y>>GiSJnjb9W>J=qyTo%4}8a`4UZtEAgq|zc66pUSLgBS zT^J=bwG_C`Ef!>udJ>^W!-5IEJzWHpfN+`r#@sym{vHBb4V(;D&I8OXMji8&5JqrX z0!|YcO8wNJ;b=S(5@wAQQ@Omhaub{ismS4U<+=&6Wex7t5*>D~Ra0@*x62c~EcRWL zBBrW(47Qa=4ykiwWNe@bDxny!o9PqOPW8VNfYzW{6`d#EuYd7};L20--i#+_eeCy@ zLLh`25Q~*zp|yj$V{P0!AM_e|ey=o$^z^hUqGhPE)s18zD#0?&&0RIFC{&bDbTr7r zoW-rQgD$N6;ozC!8LG@WZq;_RaT8=r!n?qILky7_f2sJoJR|e9cp+iPi4Ps(Eoymt zT{T;L8Uz~-RTt4%u=Tq5pkK;v&`JExoyAS${ircSMs7^34N^MKYu7iJcK0H!u5M20852f+-_QZ-RRG+%AC zRNBLYtZJM6)^rM4jw%#_win}tDZ1N(O5h)E{ToRR zBO~kEJYkPD6FF_oq{L$h_-!tP8>_w9$ z7W)dyWL74kSmdIzak>VCYO?wk3j4IbAs<`Ho!^es{j&&*=!n6k!>Wf2kZw@(Mu6#Z zwBfT4LbHv4kk4qHvEa?j2|%3xtj&hDOO9=7{<^)T3i&k;_NNWAz z(ivf&hj;aR!$bP{&mOadnhZRVK*2O5e8Y?)*rmT7bHab2b79H*V8Is=e_8B{dbZDD za%kJeON+Ua2DW_dwv{T$SMnX+f~&M;BHz1Cs>-XsXX`FYjv=4 zbjmLg>E&I}GG98A^2(8VLNtjVl&fhJZ=vdR5%h4Xs1IP~OL%Pe@}2UFx%hExDXNZy zo}(Q8$zE{Opx!c0c%M`j#*27L!#8)<5k;4AL9M&4YVI~!OWO4w-!6^!RQGEl+!p`m zz>Am#bZDIAkHwXk@ZL?_*o?rCO5f(U+Xn;{ap7s z+2(qG`WCna27K3WQ|B-sOy+)ihUKuBkLrKWT&%f6fHN`p4gET;P zM0xQ-Cac~F`P-jp*dpJ?o{VtM= z1TzfCo7XeVJ%VS?@xkwq21-Kr{}J`V)1k8I3K7A%qM6inS0^nP3f^l>sGimI)H6S!O*m-9y3r8*Se64=?fwc{ig{Ql$nZRq?{BYR5m&)9fnBIXw@ zbzo93(r3nmP->Q#h1ONS5XpzkLEnVvJeQ9#XVMR=-EfIq%_XWyK_l3M$`}q(NY4bn z>iT7McjrF82rr$fKhU;~0FsIZ@{GsvQZPE^B)>qcp@ zoo)VW*U~b#{{bFfCQ%Eoo}K=XG8|z*)`V*$Yt7w6T;StdxG!j8xWlId#GZ5Vd_UQz z0{uJqW&zi?V_vv4(*;KWG3$ZL|WeX>3p(S*_>AS?M69L6;wF0mvL2lYFw}25S|4T9Qr-vg%F^Q+##|^c>SK zY^k!+b;Vv(CFvXT0!&oCzOGKF?mLl9hBm{5vJ9dp;+$v`n0d0p;jyFSvI@{_J_$V? zqB>Sa0nTg1?rNp@j#09~s8TtyETXmij}bnoKXjyd|Fd4i`S*Y2tsWe#C=Zj!v(%mz$3D-p6w(5lNSfAkShc ze`OdD-G`gylZ$I1@5)hh-sRx==6FDg0?E-oO_wg@b!lKUvt^v+dkCPM7#9&Is-Tmf zLduI!tqQzhQfyJ8L+JgO5Uw0;*gtE;c}jlDtxGPa$$JA$K= zJEs8Q{XK6yivt&`qP=h1mvoyL88GeA_gS^k!7hyj;;7yP2~9*DC-R zwEB^O7TCGD(#-W|XDcvoz!(96BlJ~;QX%)hQ`yI6L^O0K3dQ{Dcn?#=FG#`m1dcC2 z;fl;pz$z1tQ&)qdS@o(xbRW>+E{X<#tjU>T$>8!VzY={AyO&77>Ei0z3v|{npEp|- zEI7h#;VSrD(}sJ`6KK(y1mZz2aJm+~x&ANX2KP5mal3HZp4C*O)O{1Z_=!UI+R1=3 zJTnQYAhBaeguhW1w>`kPB6Y6w2geBumx-;heg0QIiYF#Y+n60M(ub|`?T;oUK0|lz z4?V*77C+enLJkKP**>LLM^F9V666ne1SNJb__FhwZ&vp-NWSn?ohB z>za_p{IUPn0$3VkG4-=9wCU^Fi?H5vD61FdM$!3LA>ok~ueI16A;os)6s_aCD)bI$ z&_RA6Kycr5blQaYnX^$A55Wa?yl)TN=z}!*zYa0tLxjNV*uNp9CdI<~fjl{vjsoEl zfr!)!Nut=LW+yLd+*i*o1s3PzBMLuoJ_t=?%Q6;(JX<9rLMDJEk}T7}V8sbY6mWHa zq%>#=Keg*!4E|_Kw9tO{9`Zd&Rckan{;kN_ol9P44SQwUD<9}gC)zwuJ+u@NNd(fA z0txryNs{M5!H3NAIyS8}7kypJTbs%EvNdlrp%V8E1L2Ly=j%UH5l_G=>G$nU8eFa} z`u{y|I3XyYb^$Ryj`$gD8+T8S{q_4d3_SphZa{v1KFmmsD~Amt0=$f{F)?8d)LQyq zw6T<*6#9di=QcKiAI>{qNiB%s;Le7P$Gm_C3ut@1Z43+98%+jhnZvrj__0SgoD~1jT9kt(*&WroGSSGY9)`j8U-QYh0XE^h}aa=DwVzcFV z{!HC=QQM$LhCFTeWOVYso{iIX-d*Z5P_^9BM-P{=_BWnu+}nQw-UXq~LAO(hpz`Sx z^$bi-mlXAF6UWL*v^Y=tuT!<%h;UP8qB!>W!$er|8Kf|hmKPWxKMGr{MnGE#u)EBP zk(`b@$g;T+eZqy*)uj`4)qS)Jtgfre)J9}bhJej1ix1V<*ubFV?tZ#xH7@+x^`amXZ4|_sToO{cl&Bx*YNb&|$!((LXzdp+yee#Yvu861R|uqIf_&s0>TXukP8ofyPq5DVYLtrsGv_k zP#`Xu{0Te}wkLAuYf~{h3%}&7Id&L$KT4nY%s^dOt2CMYwus+X+Er3d;Knabh>Vd^ z@D%C!__)|;z@tN6(Y38iSS_d1ZmMl-on_KH&-LakE@^r;x$P5Q71G7SiwE8mGd=pJnu70AD^CXD4a$p zy$JaQ3|Cq>onY$*XIWtRYS5C7QV0MwfBgLE0mL8y{M%o@cKBiC^ZqU#TOkBTAc(O0 z1{STB>8zi@-yZs|l07JWrs6D~3q^fS5O=O*=h+g&2Ov|`t|60OIbuJA{QNjM<9MZ; zG1xx(di6fKpLWZcBlP)x77=fy3v(7?WndtA;zcKM0&PO2DN^@6(`l@(o9POVg^zA$ zGBEV}&i09;CMTB^j@6nn>eE8FwM;|HgsNs|X(5eDp6-OIsv{dK?rF`u$I^=DP~v}{ z8Q(I0SCf`OzVl0;=Q1)8FSX2gvw2T(kB)>Rt+T1-Hm}=C!AHIo&wlPVwdguNMF}~r z@af>~?-X>_+5NjS5%6^?Z+=km816Rc!>Go$OUeA-7eA>p3p#pny_!TIGuJwY(tJTt=(Z=x789YXH#haY+kz1d3|CgT$Sm-lLRbeW56${;RrFU`!J3l{ zI#GP3@_b~9YY8m31}hpr9WzwSE=_DUzSK5hC#1K%RwYNR(aB!on2v;lNV60F$ot%E zZg5o}OTDvIZEiG=#xjf47puZTUQafTJ$(vDh6^56>@#djoG!X*14s z%-Fhk^Y8baw66v!rp*VJ>Qh*-lNLxjG;uG>3A4*{Jp<_^06rro0X4&Ilri9B}F7(F0E<%!VBcf}z zN^Tj2#!QKvx5$t|v$GIEbw7 zC3!tRBsZ7gJb;nOKFVuIbSG20HbY-5n+7V{x=a7ve@TNqOEh2)gKe36{_d+^V;*;HaH~sc zt+4xz@ybnri_>hYrY_-X*S^p~+t(mVsw9-8mb=EsxQ)+~ypSRFEu(o$S5+5jBdOJS_3h+%WMu&4jyD4!cU=sJ{BWwUq8O7h zoq?KC3u;Oyg|R0#$NNx)?2todChI6#k;q}O43a<@(gYM%z65FI^Wxn0e>~|}YRFfhd(B@Kl=@#yji`Vsthv=muKDGP}g3^$p^_jp~&p-)*E953cS%IHIOoR+gCG);HOA0P! zB|^Y-!p%)ic`)2>W$80AvEa`q)qfk_v=$7s?9N}j{vHuT5=!~EN~ibXq6Y}of@cq?M_bRtj9d!FzNU@((P_f54&CCFs_!&sNp&8%D^23}%g= zAb^e_o@n2@ORUG;3`iYWtJ*vHQ6ukEU-<*!6Ob!8JXN>(2Um{3B7I`1gMI*soTi6! z1MI5LxxzErURZ>IDo-A%5)6$SE|FAg$KuQ_Vb=fN-e6XfB(9xF=$KDLiCB zjFn!UoHg0^d!~U#sL#FSsq6Sqex2bf!DZs{U{U?b>N+?qXEwSxxSOgpDXiWB_DOH$ zFZl_G2l4SChvF#fY>9^2+#zB|o1VIuP$tPx0|U8i74`IkHRZ4P^os-L{L8*8;rQOW zk$Tt#QqLmag$BtQ4Ahd7ry(@(#qtW=j>`Y+!s)F|FPjfZhTjOr`hAG%z*7-1X{M!x0YQASqW=r73!1RUP;mlk4|C9V*5QbN-_y z!}uQ6FcQ^+7AmK&``_z`Wi%?k3cTThoRaQ(5!5LbNyOVpfvS2PWU&Y_qx^WhQ%)x2 zvJQn-W+5_juA{c;^X<;Ecw%pco?^G8)@dF$D%y$y7Gzhkb|Rg>GraI!96!H~6dq7h z^#3&BAa3m3O#tvr06tOrxxA#z-QAs~|C$|4<8fM1Zn_6cUV`c17u2|yiE^3JlL7&h z2-CG8V2jXfof&;t2D^|Jp{cO@<{wy_ABcj6f;22x{5B}~v){A>L+5JjMgR2#JB;=R zJ-LrcVDDaOZtLk0PoSIm3m|HPexH9&cO{OiuIKA*?~D9RLV|2g^9MizVsGeEkjpu+ zi|3~o!bT%(iuG)Js#!Nsb=ZH-`|#cH4=BF_MN2$gh8Sg0H`DaYFCoYy(;_*0cc0`% zu1#ObzbcUHoAuSiH_H0mZZh% z)IM~RH-!_V#LcWDH#T!jjvnXN;mK^NmhJNTjr6;P|5;`B5y_~c zsU`x?XlDZ77ZBukOuyqN5TC|MPzUY_zOnJfepi=bU4 zont@Q%W1O}k<({q@{>9m*((n~tv{fxdE0M_vVV9>=PENa042)ll1@(-cxZ474GYM; zQlPDE@U4aJI=`pN6g=Q;pu#dSm^`pw7qGhL z!z6`6iKDOQKtdh9!fI+Jy0J4lt`3?I3V z6TJls6X4khz&5;BH~Q=Dj@zQwm^EwK{w)n@zzR*W5>Vd4u5*$urv0H$@>-v#$yx+r zq`-L!^eL|Q8>tNc1=qxN0y5bFtV=+4R~JA7qCoy<+664&>OPJHn2oTr7v>%SG6BmR zPE&s{L)~)_$q^2I#*NY(z#T;Bq`9TP`qt$;s!Usm>%9VXXt3_%ik5HsfEw-EKD14h;{9 z2wR5iU{S_|6}4lAZ>Z3p*i6BI1>a78oWD7qtUDEG47SLbGWa%-J^8zF=*lt?WJ1Q5 zPgbGlg|d`g6J0rNVzg5TkeQb=UzEFRH7q=|>N!g($mqVyGekwS4U;ReOm}wnm&@Vv z$&4-%XQ!i8pe7;643v&=t50*GLlxN+YEZ0Vh-e0uw0%eYyHN+UY=PBTbf^3PrVQ zVJG%oMN=P$M=%Glq=tsZ#vTn#RLyB6pv@}4LcX~w20B|oKjJ-X3c-4Vv)GL^1!TW% zZH0jA{|nF!Q7bFcW%dkPwg-_&T$|5eQoRm9>V-Xyg;54$Y3T)*9Txvt2O)p36E=Wn0*H6gWc2lUtqp)krbd}f&J4r0H*vq?Gef!NNyS{u#l^< zZm=P!lBH-YD&eX>)QJL#mZPn*)K;|wVq_!?Vvs8&W%@4Gg8(D{w3^j&pGJWKGe5BiwZbjGXRjHey71iP|3ID`ooOP^^$m{;AUZ5=#e@p$qbAO=@Jb#ih7DXY^fJA5NI zpbP-8bq;)atqsgkq+jW2+&ruB;WmcRm5%fAs zKLUfK6!Y_p0nU_wYpBm?RVIKYJAv9z<2^7m%U9$;!W{S3a zStbxZFp{;o-Z**6j9GhN^=`kw2^yr!;t>86C0krc!cr!~;`rZcTz~zdA+sGj2ahJp z)u7|(jqEt7&crLeyum?Pp2{*Yt(W>!pEIP?3=|Z31h@tw5riQxTdYi^6PJGrS_TIP z8+|krm5}It(ug+rU|7|<0`6*+fKP?tmu{nm-|l8b_AslKz@=_$ZB2Ck6Ko3ys<$vg z1+eNwrGnSTtvrjl$XD0W@*7yfHkX!QvD4}{T9@FUegA7iMX^CsWG4#v3_5{=DqZ~% z=$t6Oq6C-sX8AnBOwtwzTQjtY{j9&iHt6wYj{*ou?q0gngbuNfJybBI}2y-huuO?XE1=TY98tyN|eDYE>Eg~uNTFI4%s^~dM z4W~xOF%ZqkF(B&TzSFxXRC6GvBdQWZU{#19V5(uRF-l{6hZLW(XbFFsNTH-d0`QIy~Dz`eB2mo_QmxY$1}uO!GslC_Ojc5CJwW5Sg_%WLa$`q&m=@UNpz8ahr+1#WzCD9x1DSraX9YYrMV*r<4(s+X3uT`{PW zJGQ#v`$tS?0iu2A`0nvlv#3u7#`)p|BWJT)C)Z!KAogw>_y`s8$snr8@({=L*)c3X z9u_)NIkc<|Mo7(Kh)mm0EK+t1+=_iIh!uid@)UeI%x8ypazh$jdj&{)m#?sC1KX0o zxdxMaU(A8>WQmg5;9?_gGrCJl8pkY$JgO^T&A$RZPkaJrQKq{VqPG!ozg~0CgpRLG#>P!3C;-c%cyA6+iulp#I z?rlU0$>0BU?zX&iv%WqYxpk;-S*%v6WwDLKS;dp<@WL%Iv|sAY*Qjvt+TauMhU%y< zrFzUc!qYjs&aZ0g#3Lza!`BeP9dm4)wr*@+KkR|sNSwc?hV|RgyQis{qoTZEhl@hd zpQ5vY)QUJp_JolP^t+eaPd}Cnc*Nh#mv|1Lg>E}T4KG$qvFjVn$Fd-3RfC`A8Err8 zq6jTL>%AZSFY6m|I`ilKcp^QEt-tBobi;D2+zLDzo$=|)B|`79An6uzxXIR|(PKoj z!suo@-5+1_WT}!a{i8jPQ@#$>>Yg1z~b8eu$i_AkUZdJ_&;k-<1dnN0hE9FEbB zhr{etX5%AVSp<>-Lgt6mm5R*4C8)$Po+=U#ZGwy}Z(EEdzmY2ME3SPd zPCCz`4*|{RZ2d3Ae?Ag-5aA-%UFl~mQN=t2SqKWrC~KjXWtL~M%_{zCa-f5sN?Q;y z%CC+pkaARwzkCI4oaoLc-{OJq#6@#Dp^awDK`WwsDYK}ft<=TTQk4l?^B1brG!}b* zEvS79eQ*o&-L07eDI1`#$3)5E-IYB!?qD(p7Iazi<{AxB2vqFAKjG1LwF+9&-oc0C+JFlB zJ}Rit+4kp+PaL%JV+|17`j%rT`n((#c|MU)rV~pH9P6@cGd|m|Mty=G=vA4g-Gw*5 zc?G?fFpUzN%5?s0$u7=PT)%yLg>dRDU8}XcC3sLw*Mdk-xO`)=_P1OX(@rfd^l9fi> z*hFu(l7E-NIXxABOp6PDQC(wS9n7~o$3Z-=e!<`v+iUEd<47n&rF^!r)!wp*%CV62 z*$?Xr+oW_uGHcWmbEf}-fieHo6P9Vv5!FkwW(vxR&iD9fnd#G}LU$KiO7D=Lwln`3 z*+%Rj9c~+Q$hFBW{>Tlz|0|ed;b$Z5wSJ~A|x-p)Te;va20nBGLT_mU{f-Ej=$N_)LGfyK04P{4&UD^h_L);pus$jZcn5PeR-ALk} z8UHLIE&c8Nfq%WHf05)DxN_X_Pw=UfYG~9Xq)sEUAA<%4PlyX|fclDt5>&+9+}tR= zqn7jrk+UKANGIhxIVtP~+9mZqom;8SA|97WZ?9u9C#2sroVjeUXPvz`590})+hvVJ z8);p0AB}^&mh*<}`;@WR!x4LS+2SI^T{8qkpQ6Xoq~lxkrOh&G1*$|;%3>9Wi!GaT zqm`It@r9H=+SUDZxTz8g zopR?-Jwj>fCB8I8z~1(XBx3~rFM|d$%rDwhSfzOGBo1(paKk)b@;f8KHjFX2#ejC# zr%z7r<@hvKzf-@D{e4I*)Uhn2d9uiUEP`BN{9hEws=mQ&mN#pi`_>k77!L;Tj&k|k z_wcI3N>Yhe%A*`4a3?R~P2?^T7$1;W%g$q|d`vSMEb|Gm(6e`~LgjJJ#hY}-sHRY| z@Z*W&_SNbs18@`>a8XtKYPRIbl&v?Yhe*j-wpXnTvl}#)QUoyQHQzKEv~l;5Kswof zDI<>PdwHp_p}N`{^NIUnkf+G-XqW~mIwrF4R_z4 z-TT{9HC5H1^5NI|HFb3-%OAdm!y&*5enA+Kw2~kh1a$jUg*^QB>%IYgn`1%?b4F1X zOjMpMQr+6zQTRf92>hex+h6RXE5N@MPrz)bum7Xl0t)>L@H{Fv*R8et1Kz;uE{CQ6 z*8;pnKElya6*NhvPgK(SD1in^;g+7t&LVv?u}5i_I@gEGPY?p7ShU5W=L;V%fKp%i>F!>H7|2A8N=t4bKDtvftLbbbu@T=jb8m z`$N0Lz6sEVFbh_iG6VHHX&~|woe2TR$nl*-mMYb`tCxEcIEBm0VW%u+w4CTLX-FZ^ zj20gO%+tgM0nQjgZ=^97R3-8QnK^=suyjt+H|-ID5#YL*K9vntXbt zGW&$T@Pp#Gqwk_bNGmHk=vJx{Z39h~7(TqF_-^R;(MM9h+dv6TmvNVU%uUg-kRdVK|V?(#51R97piT~2tcYbuSbyoL3?IgH{T4V)+b$1!xM~3 zCh{$Eqp~n|WxNXFA><&w;uc>1n5N$$FD|Sty-*SDRKG`pMjw3}p4cp{giF%YT_QIGSVa!D#8o?i+!a2j-o z_OZu(dAfNwpZAXnmon3Bt%{K`9Jg%A+Z1@x?^Ktc3v}R9rGu zJ5n}+P=*CUCvX!zuRtN57_V#u)BimuCvx|7e*AdhC^<)Fzo$C((1DR;hA*4q$z-6; zg-!Ut5rR}o@P#M^{@4YBMy4+uqGvdOlU{$=v$o3fuKFr1;JMEG&9wQUZT3`}K9{Yk zGQCfvLtmBcof`Ekfn!EjchDwO{1$hbV4;!3w(h}4BhVzYOlRqpaAb~lF#>6T>n&xF z6>~Ob`LFR{-0e+AtQld1e8c5#_QqBkeo3fGRi!REK@89Q6eyi^=WpC{E{k-O4RoW^ zc}4#5)Y0UKaC86{`?l^booIb0aRT$O=c55iw5-O@7vxQn?Vq1K7l>X}zu>(=Pjz>0 zdx0mTE`$(H)wq`Zm`=AYE|TicV}0qN!itgb$mb#o2|tP$OG`h|HdXl#GrrQAR15HV zgKtqvz;7-HHwm39l?C9?guQ7xMGja{V7gt9K3Q+sANpgiOtiDgi34QmFI1`kyc7IE zN7atNx|!n?Y%sO8wOxQ9e4J`_;SOGJb&9cuMXOPvJ+AHg(cr=?#efCE9?jKdqbRZh z22q%>B?gP)5i`f9*mktGtLraJJq}K*c8_nx8X|t+Tcq@+XAQD+*Q&ky`J!-r4yRz6 zD?l9Ontr2620t^*CkmLzF;ZAy3R(BBLWGM@>dHiH;`z+|XBKUocNSl7laQ_(G5sn% zm!4O*zxsdfe)DxwmsP2g5UnhVIZ!?k5jsauJk9w}hZg^LB?^R<+YY0LK|2A`CfX21 zY9_`cD0!?iEKnV5yt>Ou_c@nhEc{DQXW-4g(7Mg8_SX91WXi+kdhAd0N4=vzWk28J z*!uBt6RBJ9o{UwfjTUY`ECoyV1^X@6H4%GNsS#G?k}tWc3z9Cib`dSfSqiuvlT5Qd ztRi^M9-4S{JLiq2KJL6&u7_7orM{GSr&89LEKs2rg~SL4!JYAEJ#+MWP%_qjhsM~- z;*&4=Ib6l^DzO!#i*5<3l#P5{xGF1?5;M3&ikfpQJFDSG{RugaZwWcV@ZvxR3Drx% zL}H&MTggl{Nh)w`xYsz@0HF_GXfaFIaDq?0V$Z4bV{jB7G@otyj2iJam28cljINC5N zMK0M>d4u8rRN7ftDX&_4dJoomDL0e5$P(ZSR0U$p%MDM*O6~Ddu5fL=BJPMbJ zAQLkYw>om8vS;-kfb(npZ}e)HU;&*e{)CnUMRD1P^Do8S-%k3MNmo^l=ppmEy617E zUZ>M?x?W|*2%3tZ(#AlCG_=)klHtn`={a_oc!qd8ILGBU%l~_U#S=Hf_^yZ7zEbxz zj0UA&$9GeFaNa|7dY$AU_P*Ib`Oi7?eEtHycDYdv3FL=-iTLqMPX8M(^XajF^-se& z#J?(Y9QJ#LkfJ1ai1N3Bt?i?AQ44BjC!(B^W z;K>!ePxpY;;lypPyTFgr$wlGGxA=f6n=nE{QaDlp1z@*r(cm$RIZ+p z9x#n@E%2#Iu#{d{IW9&%s?KIKT8=9m;lI-OxVO=nsjN@j7F&Uf*jnrZ#-v_NB$+Yqt^!WXqtx&E-w$7P-+c*R2)Oe`4ideU{~~ zOy9`we{Fkr-G(B4LU7#C;-|D3kCK}btp9BiKFXILU1`E9AX0XUP%Dz#=O7lXj#Zek z`9jQ{=JhN4LGvm?Iz&i> z`3w;qsTc`yrY;d&vbAKSc{Sy~*diJ`#^00zCruG3$cgO&RFz5acTHtvF>s|amjYFd zw!PW9stg4UVokj~81nooV?mmQ$9eXnNJ`-hx~lQvF+9FM3D@T4E`e#^b+hvd)E7># zaGxXq0b`f#k@LUjCzzkDhx0ew04&)CkPCmQ&Qr3(iaY^@D)s04TbQjRlbD!zCXb(a zW1_peyY-u&o!!Cn)5DWoppw3UK?Agfso_s7?u6su?jC63lse3{{e8B!xUg^yb6Nth z`}5=VB>%_W+Z9t3Y|202hL%Du$Ts$PF_Fc7bA3Jf?!~`~7f+5O2}E7up_Xtkf@UZh zLmGTG0FL&x3nbZSXsh;cqfu$gzf`C2t~3+pOfM?@6e(CG0((@m@l?qqzT6wVPgZ0* zlV*Q)*AT5MaUp*a;0X0fLKJuj5(<{oGZ1mZH3dvXx_#+6$}YZ#)+^;GSyOK z?%(037YG>pPw?+nzJFD|s)NQ!s8{+s9Zsmjw_Hy?3O_)-Z}N<9>Mb6%#p|=nAzN#B zNH{#Sr0yuvD5@vz>3MV8-dKDqq@4iHTu&4K816vKjEyVHI{$bjn^;7y zNmV(psq7%r`g1`;OnLdI;lbB6bUC@vmuHnE9?HvtmCkJF%nDHL2z+#b1W7IlSqUyY zIaJoYxk{DHvO1t1?}m5uG1p>CN~Ie?O3`yC+(TXeW}Kso-ty}{2$uik-&C6J9SRFRy*m3->(aV=#0F~AB=I=EujEj+xF(qSgc0Sgc6zFTqGQpYD zIK|sAzhqmYUp%a|^ zpv`zf6j33#;p*)>R@4Rwrv53sZmP8cQ|*-*m%mAnCTg;IcWc^TyA`O9Y_=cj7m>~9 zX_oJl7C1*)@eFykF|un6v-q2RJU#rlB|fP-ne^MZR)U$Va{0T6$vvJRt

ToS2x1#vrlp!35Wd1wMg>hK2|k8q>eK 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"a^Vj|oYa99wZ3gR;&>=y7jbhdym5b752 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 From 37985411a2df00ba0b3cff2a934eb31f2d080f95 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 14:24:27 +0200 Subject: [PATCH 047/314] change path of eGo class --- ego/ego_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 763c0276..b4573f1e 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -26,7 +26,7 @@ # http://github.com/libspatialindex/libspatialindex/wiki/1.-Getting-Started from tools.utilities import get_scenario_setting, get_time_steps from tools.io import geolocation_buses, etrago_from_oedb - from tools.results import eGo + from tools.io import eGo from sqlalchemy.orm import sessionmaker from egoio.tools import db from etrago.tools.io import results_to_oedb From afa5b0acffda2adffa479db425372622eccde328 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 14:24:57 +0200 Subject: [PATCH 048/314] remove eGo Class to io --- ego/tools/results.py | 278 +++++++++++-------------------------------- 1 file changed, 71 insertions(+), 207 deletions(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index af80ab78..6d7a5e78 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -11,7 +11,7 @@ """ __copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ - "Flensburg, Centre for Sustainable Energy Systems" + "Flensburg, Centre for Sustainable Energy Systems" __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" __author__ = "wolfbunke" @@ -24,138 +24,9 @@ import pandas as pd import numpy as np from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, - curtailment, gen_dist, - storage_distribution, - plot_voltage,plot_residual_load) - -class egoBasic(): - """eGo basics class. - - Parameters - ---------- - - eTraGo : Network - Network container of eTraGo based on PyPSA - eDisGo : Network - Network container of eDisGo based on PyPSA - args : dict - Dict of the scenario_setting.json - - """ - - def __init__(self, eTraGo, *args, **kwargs): - - self.eTraGo = eTraGo - self.eDisGo = None - self.scn_name = kwargs.get('scn_name', 'Status Quo') - - def __repr__(self): - - r = ('eGoResults is created.') - if not self.eTraGo: - r += "\nThe results does not incluede eTraGo results" - if not self.eDisGo: - r += "\nThe results does not incluede eDisGo results" - return r - - -class eTraGoResults(egoBasic): - """eTraGo Results - - This module contains all results of eTraGo for eGo. - - - Examples - -------- - - The module can be used by ``etg = eTraGoResults()`` - - See also - -------- - The `eTraGo`_ documentation. - - References - ---------- - .. _eTraGo: - `eTraGo `_, \ - eTraGo Documentation. - """ - - def __init__(self,eTraGo, *args, **kwargs): - super().__init__(eTraGo, *args, **kwargs) - self.scn_name = kwargs.get('scn_name', 'Status Quo') - self.etrago = pd.DataFrame() - self.etrago.gernator = None - self.etrago.storage_charges = total_storage_charges(eTraGo) - self.etrago.storage_costs = etrago_storages(eTraGo) - self.etrago.operating_costs = etrago_operating_costs(eTraGo) - - #methods imported from eTraGo - eTraGo.plot_line_loading = plot_line_loading - - eTraGo.plot_stacked_gen = plot_stacked_gen - - eTraGo.curtailment = curtailment - - eTraGo.gen_dist = gen_dist - - eTraGo.storage_distribution = storage_distribution - - eTraGo.plot_voltage = plot_voltage - - eTraGo.plot_residual_load = plot_residual_load - - #self.etrago.gernator = create_etrago_results(eTraGo, scn_name) - - - - - - -class eDisGoResults(egoBasic): - """ eDisGo Results - - This module contains all results of eDisGo for eGo. - - ToDo - ---- - - add eDisGo - - add iteration for multiple ding0 grids - - """ - def __init__(self,eDisGo): - super().__init__(eDisGo) - self.edisgo = pd.DataFrame() - - pass - - -class eGo(eTraGoResults): - """Main eGo module which including all results and main functionalities. - - - Parameters - ---------- - eTraGo : Network - - eDisGo : Network - - - - ToDo - ---- - - add eDisGo - """ - def __init__(self,eTraGo, scn_name): - super().__init__(eTraGo, scn_name) - #super().__init__(eDisGo) - self.total = pd.DataFrame() - # add total results here - - # write_results_to_db(): - logging.info('Initialisation of eGo Results') - pass - + curtailment, gen_dist, + storage_distribution, + plot_voltage, plot_residual_load) def total_storage_charges(network): @@ -193,35 +64,33 @@ def total_storage_charges(network): Sum of optimal installed power capacity """ - charge = network.storage_units_t.p[network.storage_units_t.\ - p[network.storage_units[network.storage_units.\ - p_nom_opt>0].index].values>0.].\ - groupby(network.storage_units.carrier, axis=1).sum().sum() + charge = network.storage_units_t.p[network.storage_units_t. + p[network.storage_units[network.storage_units. + p_nom_opt > 0].index].values > 0.].\ + groupby(network.storage_units.carrier, axis=1).sum().sum() - discharge = network.storage_units_t.p[network.storage_units_t.\ - p[network.storage_units[network.storage_units.\ - p_nom_opt>0].index].values<0.].\ - groupby(network.storage_units.carrier, axis=1).sum().sum() + discharge = network.storage_units_t.p[network.storage_units_t. + p[network.storage_units[network.storage_units. + p_nom_opt > 0].index].values < 0.].\ + groupby(network.storage_units.carrier, axis=1).sum().sum() + count = network.storage_units.bus[network.storage_units.p_nom_opt > 0].\ + groupby(network.storage_units.carrier, axis=0).count() - count = network.storage_units.bus[network.storage_units.p_nom_opt>0].\ - groupby(network.storage_units.carrier, axis=0).count() - - p_nom_sum = network.storage_units.p_nom.groupby(network.storage_units.\ - carrier, axis=0).sum() - - p_nom_o_sum = network.storage_units.p_nom_opt.groupby(network.storage_units.\ - carrier, axis=0).sum() - p_nom_o = p_nom_sum - p_nom_o_sum # Zubau + p_nom_sum = network.storage_units.p_nom.groupby(network.storage_units. + carrier, axis=0).sum() + p_nom_o_sum = network.storage_units.p_nom_opt.groupby(network.storage_units. + carrier, axis=0).sum() + p_nom_o = p_nom_sum - p_nom_o_sum # Zubau results = pd.concat([charge.rename('charge'), discharge.rename('discharge'), - p_nom_sum, count.rename('total_units'),p_nom_o\ - .rename('extension'),],axis=1, join='outer') - + p_nom_sum, count.rename('total_units'), p_nom_o + .rename('extension'), ], axis=1, join='outer') return results + def etrago_storages(network): """Function for storage and grid expantion costs of eTraGo. @@ -243,7 +112,6 @@ def etrago_storages(network): return storages - def etrago_operating_costs(network): """ Function to get all operating costs of eTraGo. @@ -260,7 +128,7 @@ def etrago_operating_costs(network): -------- - losses - - grid losses : amount and costs + - grid losses : amount and costs - use calc_line_losses(network) from etrago pf_post_lopf ToDo @@ -272,12 +140,13 @@ def etrago_operating_costs(network): etg = network #etg = eTraGo # groupby v_nom - power_price = etg.generators_t.p[etg.generators[etg.generators.\ - control!='Slack'].index]* etg.generators.\ - marginal_cost[etg.generators[etg.generators.\ - control!='Slack'].index] # without Slack + power_price = etg.generators_t.p[etg.generators[etg.generators. + control != 'Slack'].index] * etg.generators.\ + marginal_cost[etg.generators[etg.generators. + control != 'Slack'].index] # without Slack - power_price = power_price.groupby(etg.generators.carrier, axis=1).sum().sum() + power_price = power_price.groupby( + etg.generators.carrier, axis=1).sum().sum() power_price etg.buses_t.marginal_price @@ -330,6 +199,7 @@ def edisgo_grid_investment(network): """ pass + def get_generator_investment(network, scn_name): """ Get investment costs per carrier/gernator. @@ -344,9 +214,8 @@ def get_generator_investment(network, scn_name): etg = network path = os.getcwd() - filename='investment_costs.csv' - invest = pd.DataFrame.from_csv(path +'/data/'+filename) - + filename = 'investment_costs.csv' + invest = pd.DataFrame.from_csv(path + '/data/'+filename) if scn_name in ['SH Status Quo', 'Status Quo']: invest_scn = 'Status Quo' @@ -358,13 +227,13 @@ def get_generator_investment(network, scn_name): invest_scn = 'eGo 100' gen_invest = pd.concat([invest[invest_scn], - etg.generators.groupby('carrier')['p_nom'].sum()], - axis=1, join='inner') - - gen_invest = pd.concat([invest[invest_scn],etg.generators.groupby('carrier')\ - ['p_nom'].sum()], axis=1, join='inner') - gen_invest['carrier_costs'] = gen_invest[invest_scn] * gen_invest['p_nom'] *1000 # in MW + etg.generators.groupby('carrier')['p_nom'].sum()], + axis=1, join='inner') + gen_invest = pd.concat([invest[invest_scn], etg.generators.groupby('carrier') + ['p_nom'].sum()], axis=1, join='inner') + gen_invest['carrier_costs'] = gen_invest[invest_scn] * \ + gen_invest['p_nom'] * 1000 # in MW return gen_invest @@ -392,47 +261,42 @@ def investment_costs(network): # storages # get total storage investment costs # unit of costs? - installed_storages = etg.storage_units[etg.storage_units.p_nom_opt!=0] + installed_storages = etg.storage_units[etg.storage_units.p_nom_opt != 0] costs = sum(installed_storages.capital_cost * installed_storages.p_nom_opt) - invest= invest.append({'storage_costs': costs}, ignore_index=True) - + invest = invest.append({'storage_costs': costs}, ignore_index=True) # get storage costs per voltage level - loc = etg.storage_units[etg.storage_units.p_nom_opt!=0]['bus'] + loc = etg.storage_units[etg.storage_units.p_nom_opt != 0]['bus'] v_level = etg.buses.loc[loc, :]['v_nom'] - installed_storages= installed_storages.assign(v_nom=0) + installed_storages = installed_storages.assign(v_nom=0) - for i,k in v_level.iteritems(): - installed_storages.loc[installed_storages[installed_storages.bus==i].index, 'v_nom'] = k + for i, k in v_level.iteritems(): + installed_storages.loc[installed_storages[installed_storages.bus == + i].index, 'v_nom'] = k storage_level = installed_storages.groupby('v_nom')['capital_cost'].sum() - # Line extentation costs # (eTraGo.lines.s_nom_opt - eTraGo.lines.s_nom) * eTraGo.lines.capital_cost line_expen = (etg.lines.groupby('v_nom')['s_nom_opt'].sum() - - etg.lines.groupby('v_nom')['s_nom'].sum()) + - etg.lines.groupby('v_nom')['s_nom'].sum()) if line_expen.sum() <= 0: print('Warning: !line extentation, set random costs for plotting!') - lines_level = pd.DataFrame([[110.,722*np.exp(8)],[220.,822*np.exp(8)],\ - [380.,999*np.exp(9)]], columns=['v_nom','capital_cost']).\ - groupby('v_nom')['capital_cost'].sum() - - - invest= invest.assign(line_costs=lines_level.sum()) - - + lines_level = pd.DataFrame([[110., 722*np.exp(8)], [220., 822*np.exp(8)], + [380., 999*np.exp(9)]], columns=['v_nom', 'capital_cost']).\ + groupby('v_nom')['capital_cost'].sum() - #invest.transpose() + invest = invest.assign(line_costs=lines_level.sum()) + # invest.transpose() # transfomers expantion costs return invest -def create_etrago_results(network,scn_name): +def create_etrago_results(network, scn_name): """ Create eTraGo results @@ -445,34 +309,34 @@ def create_etrago_results(network,scn_name): etg = network etrago = pd.DataFrame() - etrago['p_nom'] = etg.generators.groupby('carrier')\ - ['p_nom'].sum() # in MW - etrago['p_nom_opt'] = etg.generators.groupby('carrier')[ - 'p_nom_opt'].sum() # in MW + etrago['p_nom'] = etg.generators.groupby('carrier')['p_nom'].sum() # in MW + etrago['p_nom_opt'] = etg.generators.groupby('carrier')[ + 'p_nom_opt'].sum() # in MW # power price - etrago['marginal_cost'] = etg.generators.groupby('carrier' - )['marginal_cost'].mean() # in in [EUR] + etrago['marginal_cost'] = etg.generators.groupby('carrier' + )['marginal_cost'].mean() # in in [EUR] # get power price by production MWh _t.p * marginal_cost - power_price = etg.generators_t.p[etg.generators[etg.generators.\ - control!='Slack'].index]* etg.generators.\ - marginal_cost[etg.generators[etg.generators.\ - control!='Slack'].index] # without Slack + power_price = etg.generators_t.p[etg.generators[etg.generators. + control != 'Slack'].index] * etg.generators.\ + marginal_cost[etg.generators[etg.generators. + control != 'Slack'].index] # without Slack - power_price = power_price.groupby(etg.generators.carrier, axis=1).sum().sum() - etrago['power_price'] = power_price + power_price = power_price.groupby( + etg.generators.carrier, axis=1).sum().sum() + etrago['power_price'] = power_price # use country code - p_by_carrier = pd.concat([etg.generators_t.p - [etg.generators[etg.generators.control!='Slack'].index], # - etg.generators_t.p[etg.generators[etg. - generators.control=='Slack'].index].iloc[:,0]. - apply(lambda x: x if x > 0 else 0)], axis=1).\ - groupby(etg.generators.carrier, axis=1).sum() # in MWh + p_by_carrier = pd.concat([etg.generators_t.p + [etg.generators[etg.generators.control != 'Slack'].index], + etg.generators_t.p[etg.generators[etg. + generators.control == 'Slack'].index].iloc[:, 0]. + apply(lambda x: x if x > 0 else 0)], axis=1).\ + groupby(etg.generators.carrier, axis=1).sum() # in MWh etrago['p'] = p_by_carrier.sum() # add invetment - result_invest = get_generator_investment(network, scn_name) + result_invest = get_generator_investment(network, scn_name) etrago = etrago.assign(investment_costs=result_invest['carrier_costs']) From e3cb2edcb55cde6213e24efc1daa2e68ce701804 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 14:25:08 +0200 Subject: [PATCH 049/314] remove eGo Class to io --- ego/tools/io.py | 331 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 231 insertions(+), 100 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 08d58fd3..7cc26c35 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -1,11 +1,13 @@ """ -Input & output functions of eGo +This file contains the eGo main class as well as input & output functions +of eGo in order to build the eGo application container. """ -__copyright__ = "ZNES" + +__copyright__ = ("Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__url__ = "https://github.com/openego/data_processing/blob/master/LICENSE" -__author__ = "wolfbunke" +__author__ = "wolf_bunke,maltesc" import sys import os @@ -15,19 +17,149 @@ from sqlalchemy import MetaData, create_engine, func from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.automap import automap_base - from geoalchemy2 import Geometry, shape # Geometry type used by SQLA + from geoalchemy2 import Geometry, shape # Geometry type used by SQLA from geoalchemy2 import * import geopandas as gpd from egoio.db_tables.model_draft import RenpassGisParameterRegion from egoio.db_tables import model_draft, grid from sqlalchemy import and_, func import pandas as pd + import numpy as np from egoio.tools import db + from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, + curtailment, gen_dist, storage_distribution, + plot_voltage, plot_residual_load) import logging logger = logging.getLogger('ego') +class egoBasic(): + """eGo basics class. + + Parameters + ---------- + + eTraGo : Network + Network container of eTraGo based on PyPSA + eDisGo : Network + Network container of eDisGo based on PyPSA + args : dict + Dict of the scenario_setting.json + + """ + + def __init__(self, eTraGo, *args, **kwargs): + + self.eTraGo = eTraGo + self.eDisGo = None + self.scn_name = kwargs.get('scn_name', 'Status Quo') + + def __repr__(self): + + r = ('eGoResults is created.') + if not self.eTraGo: + r += "\nThe results does not incluede eTraGo results" + if not self.eDisGo: + r += "\nThe results does not incluede eDisGo results" + return r + + +class eTraGoResults(egoBasic): + """eTraGo Results + + This module contains all results of eTraGo for eGo. + + + Examples + -------- + + The module can be used by ``etg = eTraGoResults()`` + + See also + -------- + The `eTraGo`_ documentation. + + References + ---------- + .. _eTraGo: + `eTraGo `_, \ + eTraGo Documentation. + """ + + def __init__(self, eTraGo, *args, **kwargs): + super().__init__(eTraGo, *args, **kwargs) + self.scn_name = kwargs.get('scn_name', 'Status Quo') + self.etrago = pd.DataFrame() + self.etrago.gernator = None + self.etrago.storage_charges = total_storage_charges(eTraGo) + self.etrago.storage_costs = etrago_storages(eTraGo) + self.etrago.operating_costs = etrago_operating_costs(eTraGo) + + # methods imported from eTraGo + eTraGo.plot_line_loading = plot_line_loading + + eTraGo.plot_stacked_gen = plot_stacked_gen + + eTraGo.curtailment = curtailment + + eTraGo.gen_dist = gen_dist + + eTraGo.storage_distribution = storage_distribution + + eTraGo.plot_voltage = plot_voltage + + eTraGo.plot_residual_load = plot_residual_load + + #self.etrago.gernator = create_etrago_results(eTraGo, scn_name) + + +class eDisGoResults(egoBasic): + """ eDisGo Results + + This module contains all results of eDisGo for eGo. + + ToDo + ---- + - add eDisGo + - add iteration for multiple ding0 grids + + """ + + def __init__(self, eDisGo): + super().__init__(eDisGo) + self.edisgo = pd.DataFrame() + + pass + + +class eGo(eTraGoResults): + """Main eGo module which including all results and main functionalities. + + + Parameters + ---------- + eTraGo : Network + + eDisGo : Network + + + + ToDo + ---- + - add eDisGo + """ + + def __init__(self, eTraGo, scn_name): + super().__init__(eTraGo, scn_name) + # super().__init__(eDisGo) + self.total = pd.DataFrame() + # add total results here + + # write_results_to_db(): + logging.info('Initialisation of eGo Results') + pass + def geolocation_buses(network, session): """ @@ -64,31 +196,33 @@ def geolocation_buses(network, session): Base.classes.renpass_gis_parameter_region # Define regions - region_id = ['DE','DK', 'FR', 'BE', 'LU', \ + region_id = ['DE', 'DK', 'FR', 'BE', 'LU', 'NO', 'PL', 'CH', 'CZ', 'SE', 'NL'] query = session.query(RenpassGISRegion.gid, RenpassGISRegion.u_region_id, - RenpassGISRegion.stat_level, RenpassGISRegion.geom, - RenpassGISRegion.geom_point) + RenpassGISRegion.stat_level, RenpassGISRegion.geom, + RenpassGISRegion.geom_point) # get regions by query and filter - Regions = [(gid, u_region_id, stat_level, shape.to_shape(geom),\ - shape.to_shape(geom_point)) for gid, u_region_id, stat_level,\ - geom, geom_point in query.filter(RenpassGISRegion.u_region_id.\ - in_(region_id)).all()] + Regions = [(gid, u_region_id, stat_level, shape.to_shape(geom), + shape.to_shape(geom_point)) for gid, u_region_id, stat_level, + geom, geom_point in query.filter(RenpassGISRegion.u_region_id. + in_(region_id)).all()] crs = {'init': 'epsg:4326'} # transform lon lat to shapely Points and create GeoDataFrame - points = [Point(xy) for xy in zip( network.buses.x, network.buses.y)] + points = [Point(xy) for xy in zip(network.buses.x, network.buses.y)] bus = gpd.GeoDataFrame(network.buses, crs=crs, geometry=points) # Transform Countries Polygons as Regions - region = pd.DataFrame(Regions, columns=['id','country','stat_level','Polygon','Point']) + region = pd.DataFrame( + Regions, columns=['id', 'country', 'stat_level', 'Polygon', 'Point']) re = gpd.GeoDataFrame(region, crs=crs, geometry=region['Polygon']) # join regions and buses by geometry which intersects busC = gpd.sjoin(bus, re, how='inner', op='intersects') - #busC + # busC # Drop non used columns - busC = busC.drop(['index_right', 'Point', 'id', 'Polygon', 'stat_level','geometry'], axis=1) + busC = busC.drop(['index_right', 'Point', 'id', 'Polygon', + 'stat_level', 'geometry'], axis=1) # add busC to eTraGo.buses network.buses['country_code'] = busC['country'] @@ -113,7 +247,7 @@ def results_to_excel(results): # write orgininal data in second sheet results.to_excel(writer, index=True, sheet_name='Results by carriers') - #add plots + # add plots # Close the Pandas Excel writer and output the Excel file. writer.save() @@ -141,7 +275,7 @@ def etrago_from_oedb(session, args): # modules from model_draft from egoio.db_tables.model_draft import EgoGridPfHvSource as Source,\ - EgoGridPfHvTempResolution as TempResolution + EgoGridPfHvTempResolution as TempResolution from etrago.tools.io import loadcfg from importlib import import_module import pypsa @@ -163,71 +297,70 @@ def map_ormclass(name): return _mapped + def dataframe_results(name, session, result_id, ormclass): + """ + Function to get pandas DataFrames by the result_id + """ - def dataframe_results( name, session, result_id, ormclass): - """ - Function to get pandas DataFrames by the result_id - """ - - query = session.query(ormclass).filter(ormclass.result_id == result_id) - - if name == 'Transformer': - name = 'Trafo' + query = session.query(ormclass).filter(ormclass.result_id == result_id) - df = pd.read_sql(query.statement, - session.bind, - index_col=name.lower() + '_id') + if name == 'Transformer': + name = 'Trafo' - if str(ormclass)[:-2].endswith('T'): - df = pd.Dataframe() + df = pd.read_sql(query.statement, + session.bind, + index_col=name.lower() + '_id') - return df + if str(ormclass)[:-2].endswith('T'): + df = pd.Dataframe() + return df def series_results(name, column, session, meta_args, result_id, ormclass): - """ - Function to get Time Series as pandas DataFrames by the result_id + """ + Function to get Time Series as pandas DataFrames by the result_id - ToDo - ---- - - check index of bus_t and soon is wrong! + ToDo + ---- + - check index of bus_t and soon is wrong! - """ - # TODO: pls make more robust - id_column = re.findall(r'[A-Z][^A-Z]*', name)[0] + '_' + 'id' - id_column = id_column.lower() + """ + # TODO: pls make more robust + id_column = re.findall(r'[A-Z][^A-Z]*', name)[0] + '_' + 'id' + id_column = id_column.lower() - query = session.query( - getattr(ormclass, id_column), - getattr(ormclass, column). - label(column)).filter(and_( - ormclass.result_id == result_id - )) + query = session.query( + getattr(ormclass, id_column), + getattr(ormclass, column). + label(column)).filter(and_( + ormclass.result_id == result_id + )) - df = pd.io.sql.read_sql(query.statement, - session.bind, - columns=[column], - index_col=id_column) + df = pd.io.sql.read_sql(query.statement, + session.bind, + columns=[column], + index_col=id_column) - df.index = df.index.astype(str) + df.index = df.index.astype(str) - # change of format to fit pypsa - df = df[column].apply(pd.Series).transpose() + # change of format to fit pypsa + df = df[column].apply(pd.Series).transpose() - try: - assert not df.empty - df.index = timeindex - except AssertionError: - print("No data for %s in column %s." % (name, column)) + try: + assert not df.empty + df.index = timeindex + except AssertionError: + print("No data for %s in column %s." % (name, column)) - return df + return df # create config for results path = os.getcwd() - config = loadcfg(path+'/tools/config.json')['results'] # add meta_args with args of results + # add meta_args with args of results + config = loadcfg(path+'/tools/config.json')['results'] # map and Database settings of etrago_from_oedb() - _prefix= 'EgoGridPfHvResult' + _prefix = 'EgoGridPfHvResult' schema = 'model_draft' packagename = 'egoio.db_tables' _pkg = import_module(packagename + '.' + schema) @@ -235,30 +368,28 @@ def series_results(name, column, session, meta_args, result_id, ormclass): carr_ormclass = 'Source' _mapped = {} - - # get metadata version = args['global']['gridversion'] - orm_meta = getattr(_pkg, _prefix + 'Meta') + orm_meta = getattr(_pkg, _prefix + 'Meta') # check result_id - result_id_in = session.query(orm_meta.result_id).filter(orm_meta.\ - result_id==result_id).all() + result_id_in = session.query(orm_meta.result_id).filter(orm_meta. + result_id == result_id).all() if result_id_in: - logger.info('Choosen result_id %s found in DB',result_id) + logger.info('Choosen result_id %s found in DB', result_id) else: logger.info('Error: result_id not found in DB') - # get meta data as args - meta = session.query(orm_meta.result_id,orm_meta.scn_name,orm_meta.calc_date, - orm_meta.user_name ,orm_meta.method, orm_meta.start_snapshot, + meta = session.query(orm_meta.result_id, orm_meta.scn_name, orm_meta.calc_date, + orm_meta.user_name, orm_meta.method, orm_meta.start_snapshot, orm_meta.end_snapshot, orm_meta.solver, orm_meta.settings - ).filter(orm_meta.result_id== result_id) + ).filter(orm_meta.result_id == result_id) - meta_df = pd.read_sql(meta.statement, meta.session.bind, index_col='result_id') + meta_df = pd.read_sql( + meta.statement, meta.session.bind, index_col='result_id') meta_args = dict(meta_df.settings[result_id]) meta_args['scn_name'] = meta_df.scn_name[result_id] @@ -268,20 +399,20 @@ def series_results(name, column, session, meta_args, result_id, ormclass): meta_args['solver'] = meta_df.solver[result_id] # get TempResolution - temp = TempResolution + temp = TempResolution - tr = session.query(temp.temp_id,temp.timesteps, - temp.resolution, temp.start_time).one() + tr = session.query(temp.temp_id, temp.timesteps, + temp.resolution, temp.start_time).one() timeindex = pd.DatetimeIndex(start=tr.start_time, periods=tr.timesteps, freq=tr.resolution) - timeindex = timeindex[meta_args['start_snapshot'] - 1: meta_args['end_snapshot'] ] + timeindex = timeindex[meta_args['start_snapshot'] - + 1: meta_args['end_snapshot']] meta_args['temp_id'] = tr.temp_id - # create df for PyPSA network network = pypsa.Network() @@ -291,27 +422,27 @@ def series_results(name, column, session, meta_args, result_id, ormclass): if pypsa.__version__ == '0.11.0': old_to_new_name = {'Generator': - {'p_min_pu_fixed': 'p_min_pu', - 'p_max_pu_fixed': 'p_max_pu', - 'source': 'carrier', - 'dispatch': 'former_dispatch'}, - 'Bus': - {'current_type': 'carrier'}, - 'Transformer': - {'trafo_id': 'transformer_id'}, - 'Storage': - {'p_min_pu_fixed': 'p_min_pu', - 'p_max_pu_fixed': 'p_max_pu', - 'soc_cyclic': 'cyclic_state_of_charge', - 'soc_initial': 'state_of_charge_initial', - 'source': 'carrier'}} + {'p_min_pu_fixed': 'p_min_pu', + 'p_max_pu_fixed': 'p_max_pu', + 'source': 'carrier', + 'dispatch': 'former_dispatch'}, + 'Bus': + {'current_type': 'carrier'}, + 'Transformer': + {'trafo_id': 'transformer_id'}, + 'Storage': + {'p_min_pu_fixed': 'p_min_pu', + 'p_max_pu_fixed': 'p_max_pu', + 'soc_cyclic': 'cyclic_state_of_charge', + 'soc_initial': 'state_of_charge_initial', + 'source': 'carrier'}} timevarying_override = True else: old_to_new_name = {'Storage': - {'soc_cyclic': 'cyclic_state_of_charge', - 'soc_initial': 'state_of_charge_initial'}} + {'soc_cyclic': 'cyclic_state_of_charge', + 'soc_initial': 'state_of_charge_initial'}} # get data into dataframes logger.info('Start building eTraGo results network') @@ -338,14 +469,15 @@ def series_results(name, column, session, meta_args, result_id, ormclass): name = name[:-1] pypsa_comp_name = name - if name == 'Storage': + if name == 'Storage': pypsa_comp_name = 'StorageUnit' - if name == 'Transformer': + if name == 'Transformer': name = 'Trafo' for col in columns: - df_series = series_results(name, col, session, meta_args, result_id, ormclass) + df_series = series_results( + name, col, session, meta_args, result_id, ormclass) # TODO: VMagPuSet? if timevarying_override and comp == 'Generator': @@ -363,8 +495,7 @@ def series_results(name, column, session, meta_args, result_id, ormclass): except (ValueError, AttributeError): print("Series %s of component %s could not be " - "imported" % (col, pypsa_comp_name)) - + "imported" % (col, pypsa_comp_name)) print('Done') logger.info('Imported eTraGo results of id = %s ', result_id) From 7b59de45562bb280839fa10d564629fb281fa5ba Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 15:06:06 +0200 Subject: [PATCH 050/314] changed logger, add function --- ego/ego_main.py | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index b4573f1e..33b7d12b 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -16,12 +16,13 @@ import pandas as pd import os +import logging if not 'READTHEDOCS' in os.environ: from etrago.appl import etrago - from tools.plots import (make_all_plots, plot_line_loading, plot_stacked_gen, - add_coordinates, curtailment, gen_dist, - storage_distribution, igeoplot) + from tools.plots import (make_all_plots, plot_line_loading, + plot_stacked_gen, add_coordinates, curtailment, + gen_dist, storage_distribution, igeoplot) # For importing geopandas you need to install spatialindex on your system # http://github.com/libspatialindex/libspatialindex/wiki/1.-Getting-Started from tools.utilities import get_scenario_setting, get_time_steps @@ -30,31 +31,14 @@ from sqlalchemy.orm import sessionmaker from egoio.tools import db from etrago.tools.io import results_to_oedb + from tools.utilities import define_logging -# ToDo: Logger should be set up more specific -import logging -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -# Logging -logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) - -logger = logging.getLogger(__name__) -ego_logger = logging.getLogger('ego') - -fh = logging.FileHandler('ego.log', mode='w') -fh.setLevel(logging.INFO) -formatter = logging.Formatter('%(asctime)s - %(name)s - \ - %(levelname)s - %(message)s') -fh.setFormatter(formatter) - -logger.addHandler(fh) -ego_logger.addHandler(fh) - +logger = define_logging(log_name='ego.log') if __name__ == '__main__': + # import scenario settings **args of eTraGo - logging.info('Start calculation') + logger.info('Start calculation') args = get_scenario_setting(json_file='scenario_setting.json') logger.info("calculation settings are used \ with Metadata: \n %s" % args) @@ -70,7 +54,7 @@ if args['global']['eTraGo']: # start eTraGo calculation eTraGo = etrago(args['eTraGo']) - + logger.info('Import eTraGo to eGo') eGo = eGo(eTraGo=eTraGo, scn_name='Status Quo') # add country code to bus and geometry (shapely) @@ -90,7 +74,7 @@ if args['eDisGo']['direct_specs']: # ToDo: add this to utilities.py - logging.info('Retrieving Specs') + logger.info('Retrieving Specs') bus_id = 25402 # 23971 @@ -102,7 +86,7 @@ # make function which links bus_id (subst_id) if args['eDisGo']['specs']: - logging.info('Retrieving Specs') + logger.info('Retrieving Specs') # ToDo make it more generic # ToDo iteration of grids # ToDo move part as function to utilities or specs @@ -118,7 +102,7 @@ if args['global']['eDisGo']: - logging.info('Starting eDisGo') + logger.info('Starting eDisGo') # ToDo move part as function to utilities or specs from datetime import datetime @@ -166,7 +150,7 @@ print(costs) # make interactive plot with folium - #logging.info('Starting interactive plot') + #logger.info('Starting interactive plot') # igeoplot(network=eTraGo, session=session, args=args) # ToDo: add eDisGo results # calculate power plant dispatch without grid utilization (either in pypsa or in renpassgis) From c8aae92102aeba0be5a09f70b5620b8d2fd0deb5 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 15:08:17 +0200 Subject: [PATCH 051/314] change logger + autopep8 --- ego/tools/specs.py | 472 +++++++++++++++++++++++---------------------- 1 file changed, 241 insertions(+), 231 deletions(-) diff --git a/ego/tools/specs.py b/ego/tools/specs.py index 680e19cf..6fc10300 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -1,19 +1,20 @@ # Import -## General Packages +# General Packages import os import pandas as pd import time if not 'READTHEDOCS' in os.environ: from sqlalchemy import distinct - from egoio.db_tables import model_draft # This gives me the specific ORM classes. + # This gives me the specific ORM classes. + from egoio.db_tables import model_draft from edisgo.grid.network import ETraGoSpecs -import logging # ToDo: Logger should be set up more specific -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) +import logging +logger = logging.getLogger('ego') # Functions + def get_etragospecs_from_db(session, bus_id, result_id): @@ -40,133 +41,141 @@ def get_etragospecs_from_db(session, specs_meta_data = {} performance = {} - specs_meta_data.update({'TG Bus ID':bus_id}) - specs_meta_data.update({'Result ID':result_id}) - + specs_meta_data.update({'TG Bus ID': bus_id}) + specs_meta_data.update({'Result ID': result_id}) # Mapping ormclass_result_meta = model_draft.__getattribute__('EgoGridPfHvResultMeta') - ormclass_result_bus = model_draft.__getattribute__('EgoGridPfHvResultBus') # Instead of using the automapper, this is the explicit alternative (from egoei.db_tables). - #ormclass_result_bus = model_draft.EgoGridPfHvResultBus # This is equivalent + # Instead of using the automapper, this is the explicit alternative (from egoei.db_tables). + ormclass_result_bus = model_draft.__getattribute__('EgoGridPfHvResultBus') + # ormclass_result_bus = model_draft.EgoGridPfHvResultBus # This is equivalent #ormclass_result_bus_t = model_draft.__getattribute__('EgoGridPfHvResultBusT') - ormclass_result_gen = model_draft.__getattribute__('EgoGridPfHvResultGenerator') - ormclass_result_gen_t = model_draft.__getattribute__('EgoGridPfHvResultGeneratorT') + ormclass_result_gen = model_draft.__getattribute__( + 'EgoGridPfHvResultGenerator') + ormclass_result_gen_t = model_draft.__getattribute__( + 'EgoGridPfHvResultGeneratorT') #ormclass_result_gen_single = model_draft.__getattribute__('EgoSupplyPfGeneratorSingle') #ormclass_result_load = model_draft.__getattribute__('EgoGridPfHvResultLoad') #ormclass_result_load_t = model_draft.__getattribute__('EgoGridPfHvResultLoadT') - ormclass_result_stor = model_draft.__getattribute__('EgoGridPfHvResultStorage') - ormclass_result_stor_t = model_draft.__getattribute__('EgoGridPfHvResultStorageT') + ormclass_result_stor = model_draft.__getattribute__( + 'EgoGridPfHvResultStorage') + ormclass_result_stor_t = model_draft.__getattribute__( + 'EgoGridPfHvResultStorageT') ormclass_source = model_draft.__getattribute__('EgoGridPfHvSource') - ormclass_aggr_w = model_draft.__getattribute__('ego_supply_aggr_weather_mview') + ormclass_aggr_w = model_draft.__getattribute__( + 'ego_supply_aggr_weather_mview') # Meta Queries - ## Check + # Check if session.query(ormclass_result_bus).filter( ormclass_result_bus.bus_id == bus_id, ormclass_result_bus.result_id == result_id - ).count() == 0: + ).count() == 0: logger.warning('Bus not found') - ## Snapshot Range + # Snapshot Range snap_idx = session.query( - ormclass_result_meta.snapshots - ).filter( - ormclass_result_meta.result_id == result_id - ).scalar( - ) + ormclass_result_meta.snapshots + ).filter( + ormclass_result_meta.result_id == result_id + ).scalar( + ) scn_name = session.query( - ormclass_result_meta.scn_name - ).filter( - ormclass_result_meta.result_id == result_id - ).scalar( - ) + ormclass_result_meta.scn_name + ).filter( + ormclass_result_meta.result_id == result_id + ).scalar( + ) if scn_name == 'SH Status Quo': scn_name = 'Status Quo' - specs_meta_data.update({'scn_name':scn_name}) + specs_meta_data.update({'scn_name': scn_name}) # Generators try: t0 = time.perf_counter() - weather_dpdnt = ['wind','solar'] - ## Conventionals + weather_dpdnt = ['wind', 'solar'] + # Conventionals t1 = time.perf_counter() - performance.update({'Generator Data Processing':t1-t0}) + performance.update({'Generator Data Processing': t1-t0}) query = session.query( - ormclass_result_gen.generator_id, # This ID is an aggregate ID (single generators aggregated) - ormclass_result_gen.p_nom, - ormclass_source.name - ).join( - ormclass_source, - ormclass_source.source_id == ormclass_result_gen.source - ).filter( - ormclass_result_gen.bus == bus_id, - ormclass_result_gen.result_id == result_id, - ormclass_source.name.notin_(weather_dpdnt)) + # This ID is an aggregate ID (single generators aggregated) + ormclass_result_gen.generator_id, + ormclass_result_gen.p_nom, + ormclass_source.name + ).join( + ormclass_source, + ormclass_source.source_id == ormclass_result_gen.source + ).filter( + ormclass_result_gen.bus == bus_id, + ormclass_result_gen.result_id == result_id, + ormclass_source.name.notin_(weather_dpdnt)) conv_df = pd.DataFrame(query.all(), - columns=[column['name'] for - column in - query.column_descriptions]) + columns=[column['name'] for + column in + query.column_descriptions]) - conv_cap = conv_df[['p_nom','name']].groupby('name').sum().T + conv_cap = conv_df[['p_nom', 'name']].groupby('name').sum().T query = session.query( - ormclass_result_gen_t.generator_id, - ormclass_result_gen_t.p - ).filter( - ormclass_result_gen_t.generator_id.in_(conv_df['generator_id']), - ormclass_result_gen_t.result_id == result_id - ) + ormclass_result_gen_t.generator_id, + ormclass_result_gen_t.p + ).filter( + ormclass_result_gen_t.generator_id.in_(conv_df['generator_id']), + ormclass_result_gen_t.result_id == result_id + ) conv_t_df = pd.DataFrame(query.all(), - columns=[column['name'] for column in query.column_descriptions]) + columns=[column['name'] for column in query.column_descriptions]) conv_t_df = pd.merge(conv_df, - conv_t_df, - on='generator_id')[[ - 'name', - 'p']] + conv_t_df, + on='generator_id')[[ + 'name', + 'p']] conv_dsptch_norm = pd.DataFrame(0.0, - index=snap_idx, - columns=list(set(conv_df['name']))) + index=snap_idx, + columns=list(set(conv_df['name']))) for index, row in conv_t_df.iterrows(): - source = row['name'] - gen_series_norm = pd.Series( - data=(row['p'] / conv_cap[source]['p_nom'] ), # Every generator normalized by installed capacity. - index=snap_idx) - conv_dsptch_norm[source] = conv_dsptch_norm[source] + gen_series_norm - - ## Renewables + source = row['name'] + gen_series_norm = pd.Series( + # Every generator normalized by installed capacity. + data=(row['p'] / conv_cap[source]['p_nom']), + index=snap_idx) + conv_dsptch_norm[source] = conv_dsptch_norm[source] + \ + gen_series_norm + + # Renewables t2 = time.perf_counter() - performance.update({'Conventional Dispatch':t2-t1}) - ### Capacities + performance.update({'Conventional Dispatch': t2-t1}) + # Capacities query = session.query( - ormclass_result_gen.generator_id, - ormclass_result_gen.p_nom, - ormclass_result_gen.p_nom_opt, - ormclass_source.name, - ormclass_aggr_w.c.w_id - ).join( - ormclass_source, - ormclass_source.source_id == ormclass_result_gen.source - ).join( - ormclass_aggr_w, - ormclass_aggr_w.c.aggr_id == ormclass_result_gen.generator_id - - ).filter( - ormclass_result_gen.bus == bus_id, - ormclass_result_gen.result_id == result_id, - ormclass_source.name.in_(weather_dpdnt), - ormclass_aggr_w.c.scn_name == scn_name) + ormclass_result_gen.generator_id, + ormclass_result_gen.p_nom, + ormclass_result_gen.p_nom_opt, + ormclass_source.name, + ormclass_aggr_w.c.w_id + ).join( + ormclass_source, + ormclass_source.source_id == ormclass_result_gen.source + ).join( + ormclass_aggr_w, + ormclass_aggr_w.c.aggr_id == ormclass_result_gen.generator_id + + ).filter( + ormclass_result_gen.bus == bus_id, + ormclass_result_gen.result_id == result_id, + ormclass_source.name.in_(weather_dpdnt), + ormclass_aggr_w.c.scn_name == scn_name) ren_df = pd.DataFrame(query.all(), columns=[column['name'] for @@ -174,9 +183,9 @@ def get_etragospecs_from_db(session, query.column_descriptions]) aggr_gens = ren_df.groupby([ - 'name', - 'w_id' - ]).agg({'p_nom': 'sum'}).reset_index() + 'name', + 'w_id' + ]).agg({'p_nom': 'sum'}).reset_index() aggr_gens.rename(columns={'p_nom': 'p_nom_aggr'}, inplace=True) @@ -185,44 +194,46 @@ def get_etragospecs_from_db(session, ### Dispatch and Curteilment query = session.query( - ormclass_result_gen_t.generator_id, # This is an aggregated generator ID (see ego_dp_powerflow_assignment_generator for info) - ormclass_result_gen_t.p, - ormclass_result_gen_t.p_max_pu # The maximum output for each snapshot per unit of p_nom for the OPF (e.g. for variable renewable generators this can change due to weather conditions; for conventional generators it represents a maximum dispatch) - ).filter( - ormclass_result_gen_t.generator_id.in_(ren_df['generator_id']), - ormclass_result_gen_t.result_id == result_id - ) + # This is an aggregated generator ID (see ego_dp_powerflow_assignment_generator for info) + ormclass_result_gen_t.generator_id, + ormclass_result_gen_t.p, + # The maximum output for each snapshot per unit of p_nom for the OPF (e.g. for variable renewable generators this can change due to weather conditions; for conventional generators it represents a maximum dispatch) + ormclass_result_gen_t.p_max_pu + ).filter( + ormclass_result_gen_t.generator_id.in_(ren_df['generator_id']), + ormclass_result_gen_t.result_id == result_id + ) ren_t_df = pd.DataFrame(query.all(), columns=[column['name'] for column in query.column_descriptions]) ren_t_df = pd.merge(ren_t_df, ren_df, on='generator_id')[[ - 'generator_id', - 'w_id', - 'name', - 'p', - 'p_max_pu']] + 'generator_id', + 'w_id', + 'name', + 'p', + 'p_max_pu']] dispatch = pd.DataFrame(0.0, index=snap_idx, columns=aggr_gens['ren_id']) curtailment = pd.DataFrame(0.0, - index=snap_idx, - columns=aggr_gens['ren_id']) + index=snap_idx, + columns=aggr_gens['ren_id']) for index, row in ren_t_df.iterrows(): gen_id = row['generator_id'] name = row['name'] w_id = row['w_id'] ren_id = int(aggr_gens[ - (aggr_gens['name'] == name) & - (aggr_gens['w_id'] == w_id)]['ren_id']) + (aggr_gens['name'] == name) & + (aggr_gens['w_id'] == w_id)]['ren_id']) - p_nom_aggr = float(aggr_gens[aggr_gens['ren_id'] == ren_id]['p_nom_aggr']) + p_nom_aggr = float( + aggr_gens[aggr_gens['ren_id'] == ren_id]['p_nom_aggr']) p_nom = float(ren_df[ren_df['generator_id'] == gen_id]['p_nom']) - p_series = pd.Series(data=row['p'], index=snap_idx) p_norm_tot_series = p_series / p_nom_aggr @@ -231,41 +242,39 @@ def get_etragospecs_from_db(session, p_curt_norm_tot_series = p_max_norm_tot_series - p_norm_tot_series - dispatch[ren_id] = dispatch[ren_id] + p_norm_tot_series curtailment[ren_id] = curtailment[ren_id] + p_curt_norm_tot_series except: logger.exception("Generators could not be queried for \ - Specs with Metadata: \n %s" %specs_meta_data) + Specs with Metadata: \n %s" % specs_meta_data) # Load # Load are not part of the Specs anymore # Storage t3 = time.perf_counter() - performance.update({'Renewable Dispatch and Curt.':t3-t2}) + performance.update({'Renewable Dispatch and Curt.': t3-t2}) try: - ## Capactiy + # Capactiy query = session.query( - ormclass_result_stor.storage_id, - ormclass_result_stor.p_nom_opt, - ormclass_result_stor.p_nom, - ormclass_result_stor.max_hours, - ormclass_source.name - ).join( - ormclass_source, - ormclass_source.source_id == ormclass_result_stor.source - ).filter( - ormclass_result_stor.bus == bus_id, - ormclass_result_stor.result_id == result_id, - ormclass_source.name == 'extendable_storage') + ormclass_result_stor.storage_id, + ormclass_result_stor.p_nom_opt, + ormclass_result_stor.p_nom, + ormclass_result_stor.max_hours, + ormclass_source.name + ).join( + ormclass_source, + ormclass_source.source_id == ormclass_result_stor.source + ).filter( + ormclass_result_stor.bus == bus_id, + ormclass_result_stor.result_id == result_id, + ormclass_source.name == 'extendable_storage') stor_df = pd.DataFrame(query.all(), - columns=[column['name'] for - column in - query.column_descriptions]) - + columns=[column['name'] for + column in + query.column_descriptions]) stor_df['capacity_MWh'] = stor_df['p_nom_opt'] * stor_df['max_hours'] @@ -274,56 +283,55 @@ def get_etragospecs_from_db(session, if row['max_hours'] >= 20.0: stor_df.at[index, 'name'] = 'ext_long_term' else: - stor_df.at[index, 'name'] = 'battery' # ToDo: find a more generic solution + # ToDo: find a more generic solution + stor_df.at[index, 'name'] = 'battery' count_bat += 1 - ### Project Specific Battery Capacity - battery_capacity = 0.0 # MWh + # Project Specific Battery Capacity + battery_capacity = 0.0 # MWh for index, row in stor_df.iterrows(): if row['name'] == 'battery': battery_capacity = battery_capacity + row['capacity_MWh'] - ## Dispatch + # Dispatch query = session.query( - ormclass_result_stor_t.storage_id, - ormclass_result_stor_t.p, - ormclass_result_stor_t.state_of_charge - ).filter( - ormclass_result_stor_t.storage_id.in_( - stor_df['storage_id']), - ormclass_result_stor_t.result_id == result_id - ) + ormclass_result_stor_t.storage_id, + ormclass_result_stor_t.p, + ormclass_result_stor_t.state_of_charge + ).filter( + ormclass_result_stor_t.storage_id.in_( + stor_df['storage_id']), + ormclass_result_stor_t.result_id == result_id + ) stor_t_df = pd.DataFrame(query.all(), - columns=[column['name'] for - column in - query.column_descriptions]) + columns=[column['name'] for + column in + query.column_descriptions]) stor_t_df = pd.merge(stor_t_df, stor_df, on='storage_id')[[ - 'storage_id', - 'name', - 'p', - 'state_of_charge']] + 'storage_id', + 'name', + 'p', + 'state_of_charge']] - ### Project Specific Battery Active Power - battery_active_power = pd.Series(0.0, index = snap_idx) + # Project Specific Battery Active Power + battery_active_power = pd.Series(0.0, index=snap_idx) for index, row in stor_t_df.iterrows(): name = row['name'] if name == 'battery': stor_series = pd.Series( - data=row['p'], # in MW - index=snap_idx) - stor_series_kW = [x * 1000 for x in stor_series] # in kW + data=row['p'], # in MW + index=snap_idx) + stor_series_kW = [x * 1000 for x in stor_series] # in kW battery_active_power = battery_active_power + stor_series_kW except: logger.exception("Storage could not be queried for \ - Specs with Metadata: \n %s" %specs_meta_data) - + Specs with Metadata: \n %s" % specs_meta_data) # Return Specs t4 = time.perf_counter() - performance.update({'Storage Data Processing and Dispatch':t4-t3}) - + performance.update({'Storage Data Processing and Dispatch': t4-t3}) specs = ETraGoSpecs(battery_capacity=battery_capacity, battery_active_power=battery_active_power, @@ -336,7 +344,7 @@ def get_etragospecs_from_db(session, # logger.info(specs_meta_data) t5 = time.perf_counter() - performance.update({'Overall time':t5-t0}) + performance.update({'Overall time': t5-t0}) # print("\n Conventional Dispatch (Normalized): \n", # conv_dsptch_norm, @@ -347,16 +355,16 @@ def get_etragospecs_from_db(session, # "\n\n Renewable Curtailment: \n", # curtailment, "\n\n") - for keys,values in performance.items(): + for keys, values in performance.items(): print(keys, ": ", values) return specs def get_etragospecs_direct(session, - bus_id, - eTraGo, - args): + bus_id, + eTraGo, + args): """ Reads eTraGo Results from Database and returns an Object of the Interface class ETraGoSpecs @@ -380,25 +388,27 @@ def get_etragospecs_direct(session, specs_meta_data = {} performance = {} - specs_meta_data.update({'TG Bus ID':bus_id}) + specs_meta_data.update({'TG Bus ID': bus_id}) ormclass_result_meta = model_draft.__getattribute__('EgoGridPfHvResultMeta') - ormclass_aggr_w = model_draft.__getattribute__('ego_supply_aggr_weather_mview') + ormclass_aggr_w = model_draft.__getattribute__( + 'ego_supply_aggr_weather_mview') ormclass_source = model_draft.__getattribute__('EgoGridPfHvSource') - snap_idx = eTraGo.snapshots + snap_idx = eTraGo.snapshots - if args['global']['recover'] == True: # If the results are beeing recovered, the scn_name cannot be used from Scenario Settings File + # If the results are beeing recovered, the scn_name cannot be used from Scenario Settings File + if args['global']['recover'] == True: result_id = args['global']['result_id'] scn_name = session.query( - ormclass_result_meta.scn_name - ).filter( - ormclass_result_meta.result_id == result_id - ).scalar( - ) + ormclass_result_meta.scn_name + ).filter( + ormclass_result_meta.result_id == result_id + ).scalar( + ) else: scn_name = args['eTraGo']['scn_name'] - specs_meta_data.update({'scn_name':scn_name}) + specs_meta_data.update({'scn_name': scn_name}) if scn_name == 'SH Status Quo': scn_name = 'Status Quo' @@ -406,40 +416,39 @@ def get_etragospecs_direct(session, # Generators t0 = time.perf_counter() - weather_dpdnt = ['wind','solar'] + weather_dpdnt = ['wind', 'solar'] - ## DF procesing + # DF procesing all_gens_df = eTraGo.generators[eTraGo.generators['bus'] == str(bus_id)] all_gens_df.reset_index(inplace=True) - all_gens_df = all_gens_df.rename(columns={'index':'generator_id'}) + all_gens_df = all_gens_df.rename(columns={'index': 'generator_id'}) all_gens_df = all_gens_df[['generator_id', 'p_nom', 'p_nom_opt', 'carrier']] names = [] for index, row in all_gens_df.iterrows(): carrier = row['carrier'] name = session.query( - ormclass_source.name - ).filter( - ormclass_source.source_id == carrier - ).scalar( - ) + ormclass_source.name + ).filter( + ormclass_source.source_id == carrier + ).scalar( + ) names.append(name) all_gens_df['name'] = names all_gens_df = all_gens_df.drop(['carrier'], axis=1) - - ## Conventionals + # Conventionals t1 = time.perf_counter() - performance.update({'Generator Data Processing':t1-t0}) + performance.update({'Generator Data Processing': t1-t0}) conv_df = all_gens_df[~all_gens_df.name.isin(weather_dpdnt)] - conv_cap = conv_df[['p_nom','name']].groupby('name').sum().T + conv_cap = conv_df[['p_nom', 'name']].groupby('name').sum().T conv_dsptch_norm = pd.DataFrame(0.0, - index=snap_idx, - columns=list(set(conv_df['name']))) + index=snap_idx, + columns=list(set(conv_df['name']))) for index, row in conv_df.iterrows(): generator_id = row['generator_id'] @@ -448,33 +457,33 @@ def get_etragospecs_direct(session, p_norm = p / conv_cap[source]['p_nom'] conv_dsptch_norm[source] = conv_dsptch_norm[source] + p_norm - ## Renewables + # Renewables t2 = time.perf_counter() - performance.update({'Conventional Dispatch':t2-t1}) - ### Capacities + performance.update({'Conventional Dispatch': t2-t1}) + # Capacities ren_df = all_gens_df[all_gens_df.name.isin(weather_dpdnt)] w_ids = [] for index, row in ren_df.iterrows(): aggr_id = row['generator_id'] w_id = session.query( - ormclass_aggr_w.c.w_id - ).filter( - ormclass_aggr_w.c.aggr_id == aggr_id, - ormclass_aggr_w.c.scn_name == scn_name - ).scalar( - ) + ormclass_aggr_w.c.w_id + ).filter( + ormclass_aggr_w.c.aggr_id == aggr_id, + ormclass_aggr_w.c.scn_name == scn_name + ).scalar( + ) w_ids.append(w_id) - ren_df = ren_df.assign(w_id=pd.Series(w_ids, index=ren_df.index)) - ren_df.dropna(inplace=True) ##This should be unnecessary (and I think it isnt) + # This should be unnecessary (and I think it isnt) + ren_df.dropna(inplace=True) aggr_gens = ren_df.groupby([ - 'name', - 'w_id' - ]).agg({'p_nom': 'sum'}).reset_index() + 'name', + 'w_id' + ]).agg({'p_nom': 'sum'}).reset_index() aggr_gens.rename(columns={'p_nom': 'p_nom_aggr'}, inplace=True) @@ -485,18 +494,19 @@ def get_etragospecs_direct(session, index=snap_idx, columns=aggr_gens['ren_id']) curtailment = pd.DataFrame(0.0, - index=snap_idx, - columns=aggr_gens['ren_id']) + index=snap_idx, + columns=aggr_gens['ren_id']) for index, row in ren_df.iterrows(): gen_id = row['generator_id'] name = row['name'] w_id = row['w_id'] ren_id = int(aggr_gens[ - (aggr_gens['name'] == name) & - (aggr_gens['w_id'] == w_id)]['ren_id']) + (aggr_gens['name'] == name) & + (aggr_gens['w_id'] == w_id)]['ren_id']) - p_nom_aggr = float(aggr_gens[aggr_gens['ren_id'] == ren_id]['p_nom_aggr']) + p_nom_aggr = float( + aggr_gens[aggr_gens['ren_id'] == ren_id]['p_nom_aggr']) p_nom = float(ren_df[ren_df['generator_id'] == gen_id]['p_nom']) p_series = eTraGo.generators_t.p[str(gen_id)] @@ -512,27 +522,27 @@ def get_etragospecs_direct(session, # Storage t3 = time.perf_counter() - performance.update({'Renewable Dispatch and Curt.':t3-t2}) - ## Capactiy + performance.update({'Renewable Dispatch and Curt.': t3-t2}) + # Capactiy stor_df = eTraGo.storage_units[eTraGo.storage_units['bus'] == str(bus_id)] stor_df.reset_index(inplace=True) - stor_df = stor_df.rename(columns={'index':'storage_id'}) + stor_df = stor_df.rename(columns={'index': 'storage_id'}) stor_df = stor_df[[ - 'storage_id', - 'p_nom_opt', - 'p_nom', - 'max_hours', - 'carrier']] + 'storage_id', + 'p_nom_opt', + 'p_nom', + 'max_hours', + 'carrier']] names = [] for index, row in stor_df.iterrows(): carrier = row['carrier'] name = session.query( - ormclass_source.name - ).filter( - ormclass_source.source_id == carrier - ).scalar( - ) + ormclass_source.name + ).filter( + ormclass_source.source_id == carrier + ).scalar( + ) names.append(name) @@ -546,17 +556,18 @@ def get_etragospecs_direct(session, if row['max_hours'] >= 20.0: stor_df.at[index, 'name'] = 'ext_long_term' else: - stor_df.at[index, 'name'] = 'battery' # ToDo: find a more generic solution + # ToDo: find a more generic solution + stor_df.at[index, 'name'] = 'battery' count_bat += 1 -### Project Specific Battery Capacity - battery_capacity = 0.0 # MWh +# Project Specific Battery Capacity + battery_capacity = 0.0 # MWh for index, row in stor_df.iterrows(): if row['name'] == 'battery': battery_capacity = battery_capacity + row['capacity_MWh'] - ### Project Specific Battery Active Power - battery_active_power = pd.Series(0.0, index = snap_idx) + # Project Specific Battery Active Power + battery_active_power = pd.Series(0.0, index=snap_idx) for index, row in stor_df.iterrows(): name = row['name'] stor_id = row['storage_id'] @@ -566,7 +577,7 @@ def get_etragospecs_direct(session, battery_active_power = battery_active_power + stor_series_kW t4 = time.perf_counter() - performance.update({'Storage Data Processing and Dispatch':t4-t3}) + performance.update({'Storage Data Processing and Dispatch': t4-t3}) specs = ETraGoSpecs(battery_capacity=battery_capacity, battery_active_power=battery_active_power, @@ -578,9 +589,9 @@ def get_etragospecs_direct(session, ren_curtailment=curtailment) t5 = time.perf_counter() - performance.update({'Overall time':t5-t0}) + performance.update({'Overall time': t5-t0}) - #print(performance) + # print(performance) # print("\n Conventional Dispatch (Normalized): \n", # conv_dsptch_norm, @@ -598,16 +609,15 @@ def get_etragospecs_direct(session, def get_mvgrid_from_bus_id(session, - bus_id): + bus_id): # Mapping ormclass_hvmv_subst = model_draft.__getattribute__('EgoGridHvmvSubstation') subst_id = session.query( - ormclass_hvmv_subst.subst_id - ).filter( - ormclass_hvmv_subst.otg_id == bus_id - ).scalar( - ) - #ToDo Check if subst_id is really the mv grid ID + ormclass_hvmv_subst.subst_id + ).filter( + ormclass_hvmv_subst.otg_id == bus_id + ).scalar( + ) + # ToDo Check if subst_id is really the mv grid ID # Anyway, this should be adapted by Dingo return subst_id - From 0c2fd7f9ebd617879a5adb6a397dada37994010e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 15:08:44 +0200 Subject: [PATCH 052/314] add logger func + autopep8 --- ego/tools/utilities.py | 50 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index 6f8e6454..5375340e 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -1,13 +1,48 @@ """ Utility functions of eGo -""" - +""" import os import pandas as pd import json -# import scenario settings **args +import logging + +__copyright__ = ("Flensburg University of Applied Sciences, " + "Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke" + + +def define_logging(log_name='ego.log'): + """Helpers to log your modeling process with eGo and defines all settings. + + + """ + # ToDo: Logger should be set up more specific + logging.basicConfig(level=logging.INFO) + logger = logging.getLogger(__name__) + + # Logging + logging.basicConfig(format='%(asctime)s %(message)s', + level=logging.INFO) + + logger = logging.getLogger(__name__) + ego_logger = logging.getLogger('ego') + + fh = logging.FileHandler(log_name, mode='w') + fh.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s - %(name)s - \ + %(levelname)s - %(message)s') + fh.setFormatter(formatter) + + logger.addHandler(fh) + ego_logger.addHandler(fh) + return ego_logger + + +# import scenario settings **args def get_scenario_setting(json_file='scenario_setting.json'): """ Get and open json file with scenaio settings of eGo @@ -21,14 +56,14 @@ def get_scenario_setting(json_file='scenario_setting.json'): path = os.getcwd() # add try ego/ print(path) - with open(path +'/'+json_file) as f: - scn_set = json.load(f) + with open(path + '/'+json_file) as f: + scn_set = json.load(f) if scn_set['global'].get('eTraGo') == True: print('Use eTraGo settings') sh_scen = ["SH Status Quo", "SH NEP 2035", "SH eGo 100"] if scn_set['eTraGo'].get('scn_name') in sh_scen and scn_set['eTraGo'].\ - get('gridversion') == "v0.3.0": + get('gridversion') == "v0.3.0": scn_set['eTraGo']['gridversion'] = None if scn_set['global'].get('eDisGo') == True: @@ -36,6 +71,7 @@ def get_scenario_setting(json_file='scenario_setting.json'): return scn_set + def get_time_steps(args): """ Get time step of calculation by scenario settings. @@ -50,7 +86,7 @@ def get_time_steps(args): Number of timesteps of the calculation. """ - end = args['eTraGo'].get('end_snapshot') + end = args['eTraGo'].get('end_snapshot') start = args['eTraGo'].get('start_snapshot') time_step = end - start From ce34a19b6fd25b7c69e5599fd3effadfaf695433 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 15:09:15 +0200 Subject: [PATCH 053/314] changed logger --- ego/tools/plots.py | 568 ++++++++++++++++++++++----------------------- 1 file changed, 281 insertions(+), 287 deletions(-) diff --git a/ego/tools/plots.py b/ego/tools/plots.py index 45ad147b..1e978d14 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -15,9 +15,9 @@ import os if not 'READTHEDOCS' in os.environ: from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, - add_coordinates, curtailment, gen_dist, - storage_distribution, - plot_voltage,plot_residual_load) + add_coordinates, curtailment, gen_dist, + storage_distribution, + plot_voltage, plot_residual_load) import pyproj as proj from shapely.geometry import Polygon, Point, MultiPolygon from geoalchemy2 import * @@ -28,7 +28,7 @@ import webbrowser from egoio.db_tables.model_draft import EgoGridMvGriddistrict from egoio.db_tables.grid import EgoDpMvGriddistrict - from tools.results import eGo + from tools.io import eGo import matplotlib.pyplot as plt import logging @@ -37,118 +37,116 @@ # plot colore of Carriers def carriers_colore(): - """ - Return matplotlib colores per pypsa carrier of eTraGo - - Returns - ------- - :obj:`dict` : List of carriers and matplotlib colores - - """ - - colors = {'biomass':'green', - 'coal':'k', - 'gas':'orange', - 'eeg_gas':'olive', - 'geothermal':'purple', - 'lignite':'brown', - 'oil':'darkgrey', - 'other_non_renewable':'pink', - 'reservoir':'navy', - 'run_of_river':'aqua', - 'pumped_storage':'steelblue', - 'solar':'yellow', - 'uranium':'lime', - 'waste':'sienna', - 'wind':'skyblue', - 'slack':'pink', - 'load shedding': 'red', - 'nan':'m', - 'imports':'salmon', - '':'m'} - - return colors + """ + Return matplotlib colores per pypsa carrier of eTraGo + Returns +------- + :obj:`dict` : List of carriers and matplotlib colores + """ -def make_all_plots(network): - # make a line loading plot - plot_line_loading(network) + colors = {'biomass': 'green', + 'coal': 'k', + 'gas': 'orange', + 'eeg_gas': 'olive', + 'geothermal': 'purple', + 'lignite': 'brown', + 'oil': 'darkgrey', + 'other_non_renewable': 'pink', + 'reservoir': 'navy', + 'run_of_river': 'aqua', + 'pumped_storage': 'steelblue', + 'solar': 'yellow', + 'uranium': 'lime', + 'waste': 'sienna', + 'wind': 'skyblue', + 'slack': 'pink', + 'load shedding': 'red', + 'nan': 'm', + 'imports': 'salmon', + '': 'm'} + + return colors - # plot stacked sum of nominal power for each generator type and timestep - plot_stacked_gen(network, resolution="MW") - # plot to show extendable storages - storage_distribution(network) +def make_all_plots(network): + # make a line loading plot + plot_line_loading(network) - #plot_residual_load(network) + # plot stacked sum of nominal power for each generator type and timestep + plot_stacked_gen(network, resolution="MW") - plot_voltage(network) + # plot to show extendable storages + storage_distribution(network) - #curtailment(network) + # plot_residual_load(network) - gen_dist(network) + plot_voltage(network) - return + # curtailment(network) + gen_dist(network) + return def igeoplot(network, session, tiles=None, geoloc=None, args=None): - """ - Plot function in order to display eGo results on leaflet OSM map. - This function will open the results in your main Webbrowser - - Parameters - ---------- - - network : PyPSA - PyPSA network container - tiles : str - Folium background map style `None` as OSM or `Nasa` - geoloc : list of str - Define center of map as (lon,lat) - - Returns - ------- - - HTML Plot page - - ToDo - ---- - - implement eDisGo Polygons - - fix version problems of data - - use grid.ego_dp_hvmv_substation subst_id and otg_id - - use cluster or boxes to limit data volumn - - add Legend - - Map see: http://nbviewer.jupyter.org/gist/BibMartin/f153aa957ddc5fadc64929abdee9ff2e - """ + """ + Plot function in order to display eGo results on leaflet OSM map. + This function will open the results in your main Webbrowser + + Parameters + ---------- + + network : PyPSA + PyPSA network container + tiles : str + Folium background map style `None` as OSM or `Nasa` + geoloc : list of str + Define center of map as (lon,lat) + + Returns +------- + + HTML Plot page + + ToDo + ---- + - implement eDisGo Polygons + - fix version problems of data + - use grid.ego_dp_hvmv_substation subst_id and otg_id + - use cluster or boxes to limit data volumn + - add Legend + - Map see: http://nbviewer.jupyter.org/gist/BibMartin/f153aa957ddc5fadc64929abdee9ff2e + """ - if geoloc is None: - geoloc = [network.buses.y.mean(),network.buses.x.mean()] + if geoloc is None: + geoloc = [network.buses.y.mean(), network.buses.x.mean()] - mp = folium.Map(tiles=None,location=geoloc, control_scale=True, zoom_start=6) + mp = folium.Map(tiles=None, location=geoloc, + control_scale=True, zoom_start=6) - # add Nasa light background - if tiles == 'Nasa': - tiles = 'https://map1.vis.earthdata.nasa.gov/wmts-webmerc/VIIRS_CityLights_2012/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.jpg' - attr = ('© OpenStreetMap contributors, © CartoDB') + # add Nasa light background + if tiles == 'Nasa': + tiles = 'https://map1.vis.earthdata.nasa.gov/wmts-webmerc/VIIRS_CityLights_2012/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.jpg' + attr = ('© OpenStreetMap contributors, © CartoDB') - folium.raster_layers.TileLayer(tiles = tiles, attr=attr).add_to(mp) - else: - folium.raster_layers.TileLayer('OpenStreetMap').add_to(mp) - # 'Stamen Toner' OpenStreetMap + folium.raster_layers.TileLayer(tiles=tiles, attr=attr).add_to(mp) + else: + folium.raster_layers.TileLayer('OpenStreetMap').add_to(mp) + # 'Stamen Toner' OpenStreetMap - # Legend name - bus_group = folium.FeatureGroup(name='Buses') - # add buses + # Legend name + bus_group = folium.FeatureGroup(name='Buses') + # add buses - # get scenario name from args - scn_name = args['eTraGo']['scn_name'] - version = args['eTraGo']['gridversion'] + # get scenario name from args + scn_name = args['eTraGo']['scn_name'] + version = args['eTraGo']['gridversion'] - for name, row in network.buses.iterrows(): - popup = """ Bus: {}
+ for name, row in network.buses.iterrows(): + popup = """ Bus: {}
carrier: {}
control: {}
type:{}
@@ -159,49 +157,48 @@ def igeoplot(network, session, tiles=None, geoloc=None, args=None): sub_network:{}
Scenario: {}
version: {}
- """.format(row.name, scn_name,row['carrier'], - row['control'],row['type'],row['v_nom'],row['v_mag_pu_set'], - row['v_mag_pu_min'],row['v_mag_pu_max'],row['sub_network'] - ,version) # add Popup values use HTML for formating - folium.Marker([row["y"], row["x"]], popup=popup ).add_to(bus_group) - - - # Prepare lines - line_group = folium.FeatureGroup(name='Lines') - - # get line Coordinates - x0 = network.lines.bus0.map(network.buses.x) - x1 = network.lines.bus1.map(network.buses.x) - - y0 = network.lines.bus0.map(network.buses.y) - y1 = network.lines.bus1.map(network.buses.y) - - # get content - text = network.lines - - # color map lines - colormap = cm.linear.Set1.scale(text.s_nom.min(), text.s_nom.max()).to_step(6) - - def convert_to_hex(rgba_color): - """ - convert rgba colors to hex - """ - red = str(hex(int(rgba_color[0]*255)))[2:].capitalize() - green = str(hex(int(rgba_color[1]*255)))[2:].capitalize() - blue = str(hex(int(rgba_color[2]*255)))[2:].capitalize() - - if blue=='0': - blue = '00' - if red=='0': - red = '00' - if green=='0': - green='00' - - return '#'+ red + green + blue - - #toDo add more parameter - for line in network.lines.index: - popup = """ Line: {}
+ """.format(row.name, scn_name, row['carrier'], + row['control'], row['type'], row['v_nom'], row['v_mag_pu_set'], + row['v_mag_pu_min'], row['v_mag_pu_max'], row['sub_network'], version) # add Popup values use HTML for formating + folium.Marker([row["y"], row["x"]], popup=popup).add_to(bus_group) + + # Prepare lines + line_group = folium.FeatureGroup(name='Lines') + + # get line Coordinates + x0 = network.lines.bus0.map(network.buses.x) + x1 = network.lines.bus1.map(network.buses.x) + + y0 = network.lines.bus0.map(network.buses.y) + y1 = network.lines.bus1.map(network.buses.y) + + # get content + text = network.lines + + # color map lines + colormap = cm.linear.Set1.scale( + text.s_nom.min(), text.s_nom.max()).to_step(6) + + def convert_to_hex(rgba_color): + """ + convert rgba colors to hex + """ + red = str(hex(int(rgba_color[0]*255)))[2:].capitalize() + green = str(hex(int(rgba_color[1]*255)))[2:].capitalize() + blue = str(hex(int(rgba_color[2]*255)))[2:].capitalize() + + if blue == '0': + blue = '00' + if red == '0': + red = '00' + if green == '0': + green = '00' + + return '#' + red + green + blue + + # toDo add more parameter + for line in network.lines.index: + popup = """ Line: {}
version: {}
v_nom: {}
s_nom: {}
@@ -210,162 +207,159 @@ def convert_to_hex(rgba_color): g_pu: {}
terrain_factor: {}
""".format(line, version, text.v_nom[line], - text.s_nom[line], text.capital_cost[line], - text.g[line],text.g_pu[line], - text.terrain_factor[line] - ) - # ToDo make it more generic - def colormaper(): - l_color =[] - if colormap.index[6] >= text.s_nom[line] > colormap.index[5]: - l_color = colormap.colors[5] - elif colormap.index[5] >= text.s_nom[line] > colormap.index[4]: - l_color = colormap.colors[4] - elif colormap.index[4] >= text.s_nom[line] > colormap.index[3]: - l_color = colormap.colors[3] - elif colormap.index[3] >= text.s_nom[line] > colormap.index[2]: - l_color = colormap.colors[2] - elif colormap.index[2] >= text.s_nom[line] > colormap.index[1]: - l_color = colormap.colors[1] - elif colormap.index[1] >= text.s_nom[line] >= colormap.index[0]: - l_color = colormap.colors[0] - else: - l_color = (0.,0.,0.,1.) - return l_color - - l_color =colormaper() - - folium.PolyLine(([y0[line], x0[line]], [y1[line], x1[line]]), - popup=popup, color=convert_to_hex(l_color)).\ - add_to(line_group) - - # add grod districs - grid_group = folium.FeatureGroup(name='Grid district') - subst_id = list(network.buses.index) - district = prepareGD(session, subst_id , version) - # todo does not work with k-mean Cluster - #folium.GeoJson(district).add_to(grid_group) - - # add layers and others - colormap.caption = 'Colormap of Lines s_nom' - mp.add_child(colormap) - - # Add layer groups - bus_group.add_to(mp) - line_group.add_to(mp) - grid_group.add_to(mp) - folium.LayerControl().add_to(mp) - - plugins.Fullscreen( - position='topright', - title='Fullscreen', - title_cancel='Exit me', - force_separate_button=True).add_to(mp) - - - # Save Map - mp.save('map.html') - - # Display htm result from consol - new = 2 # open in a new tab, if possible - # open a public URL, in this case, the webbrowser docs - path = os.getcwd() - url = path+"/map.html" - webbrowser.open(url,new=new) - - -def prepareGD(session, subst_id= None, version=None ): - - if version == 'v0.2.11': - query = session.query(EgoDpMvGriddistrict.subst_id, EgoDpMvGriddistrict.geom) - - Regions = [(subst_id,shape.to_shape(geom)) for subst_id, geom in - query.filter(EgoDpMvGriddistrict.version == version , - EgoDpMvGriddistrict.subst_id.in_(subst_id)).all()] - # toDo add values of sub_id etc. to popup - else: - query = session.query(EgoGridMvGriddistrict.subst_id, EgoGridMvGriddistrict.geom) - Regions = [(subst_id,shape.to_shape(geom)) for subst_id, geom in - query.all()] - - - region = pd.DataFrame(Regions, columns=['subst_id','geometry']) - crs = {'init': 'epsg:3035'} - region = gpd.GeoDataFrame(Regions, columns=['subst_id','geometry'],crs=crs) - - return region + text.s_nom[line], text.capital_cost[line], + text.g[line], text.g_pu[line], + text.terrain_factor[line] + ) + # ToDo make it more generic + + def colormaper(): + l_color = [] + if colormap.index[6] >= text.s_nom[line] > colormap.index[5]: + l_color = colormap.colors[5] + elif colormap.index[5] >= text.s_nom[line] > colormap.index[4]: + l_color = colormap.colors[4] + elif colormap.index[4] >= text.s_nom[line] > colormap.index[3]: + l_color = colormap.colors[3] + elif colormap.index[3] >= text.s_nom[line] > colormap.index[2]: + l_color = colormap.colors[2] + elif colormap.index[2] >= text.s_nom[line] > colormap.index[1]: + l_color = colormap.colors[1] + elif colormap.index[1] >= text.s_nom[line] >= colormap.index[0]: + l_color = colormap.colors[0] + else: + l_color = (0., 0., 0., 1.) + return l_color + + l_color = colormaper() + + folium.PolyLine(([y0[line], x0[line]], [y1[line], x1[line]]), + popup=popup, color=convert_to_hex(l_color)).\ + add_to(line_group) + + # add grod districs + grid_group = folium.FeatureGroup(name='Grid district') + subst_id = list(network.buses.index) + district = prepareGD(session, subst_id, version) + # todo does not work with k-mean Cluster + # folium.GeoJson(district).add_to(grid_group) + + # add layers and others + colormap.caption = 'Colormap of Lines s_nom' + mp.add_child(colormap) + + # Add layer groups + bus_group.add_to(mp) + line_group.add_to(mp) + grid_group.add_to(mp) + folium.LayerControl().add_to(mp) + + plugins.Fullscreen( + position='topright', + title='Fullscreen', + title_cancel='Exit me', + force_separate_button=True).add_to(mp) + + # Save Map + mp.save('map.html') + + # Display htm result from consol + new = 2 # open in a new tab, if possible + # open a public URL, in this case, the webbrowser docs + path = os.getcwd() + url = path+"/map.html" + webbrowser.open(url, new=new) + + +def prepareGD(session, subst_id=None, version=None): + + if version == 'v0.2.11': + query = session.query(EgoDpMvGriddistrict.subst_id, + EgoDpMvGriddistrict.geom) + + Regions = [(subst_id, shape.to_shape(geom)) for subst_id, geom in + query.filter(EgoDpMvGriddistrict.version == version, + EgoDpMvGriddistrict.subst_id.in_(subst_id)).all()] + # toDo add values of sub_id etc. to popup + else: + query = session.query(EgoGridMvGriddistrict.subst_id, + EgoGridMvGriddistrict.geom) + Regions = [(subst_id, shape.to_shape(geom)) for subst_id, geom in + query.all()] + + region = pd.DataFrame(Regions, columns=['subst_id', 'geometry']) + crs = {'init': 'epsg:3035'} + region = gpd.GeoDataFrame( + Regions, columns=['subst_id', 'geometry'], crs=crs) + + return region def total_power_costs_plot(eTraGo): - """ - plot power price of eTraGo - - Parameters - ---------- - eTraGo :class:`etrago.io.NetworkScenario` + """ + plot power price of eTraGo - Returns - ------- - plot :obj:`matplotlib.pyplot.show` - M€/KW ->GW/MW - - # Chare of investment costs get volume - #ego.etrago['investment_costs'].sum()/(1000*1000*1000) + """ + input eGo + Bar plot all etrago costs + """ + #fig = plt.figure(figsize=(18,10), dpi=1600) + # plt.pie(ego.etrago['p'],autopct='%.1f') + #plt.title('Procentage of power production') - ego.etrago['p'].plot(kind="pie", - subplots=True, - figsize=(10,10), - autopct='%.1f') + # max(ego.etrago['investment_costs'])/(1000*1000*1000) # T€/kW->M€/KW ->GW/MW + # Chare of investment costs get volume + # ego.etrago['investment_costs'].sum()/(1000*1000*1000) - plt.show() + ego.etrago['p'].plot(kind="pie", + subplots=True, + figsize=(10, 10), + autopct='%.1f') + plt.show() def plotting_invest(result): @@ -380,23 +374,23 @@ def plotting_invest(result): result.plot(kind='bar', ax=ax) - return def plot_storage_use(storages): - """ - Intput ego.storages - """ - - ax = storages[['charge','discharge']].plot(kind='bar', - title ="Storage usage", - stacked=True, - #table=True, - figsize=(15, 10), - legend=True, - fontsize=12) - ax.set_xlabel("Kind of Storage", fontsize=12) - ax.set_ylabel("Charge and Discharge in MWh", fontsize=12) - plt.show() - return + """ + Intput ego.storages + """ + + ax = storages[['charge', 'discharge']].plot(kind='bar', + title="Storage usage", + stacked=True, + # table=True, + figsize=( + 15, 10), + legend=True, + fontsize=12) + ax.set_xlabel("Kind of Storage", fontsize=12) + ax.set_ylabel("Charge and Discharge in MWh", fontsize=12) + plt.show() + return From afdc81774bbf06bc127280b56e659c43bf6dbade Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 15:10:27 +0200 Subject: [PATCH 054/314] add logger --- ego/tools/economics.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 09d1b89a..a8bd46bc 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -9,8 +9,12 @@ import io import pandas as pd import os +import logging +logger = logging.getLogger('ego') # calculate annuity per time step or periode + + def annuity_per_period(capex, n, wacc, t): """ Parameters @@ -27,8 +31,9 @@ def annuity_per_period(capex, n, wacc, t): t : int Timesteps in hours i : float - interest rate - ... + interest rate + ... """ - return capex * (wacc * (1 + wacc) ** n) / ((1 + wacc) ** n - 1) # ToDo change formular to hourly annuity costs + # ToDo change formular to hourly annuity costs + return capex * (wacc * (1 + wacc) ** n) / ((1 + wacc) ** n - 1) From 7beb43288f8f59397f227aae520468839d76fcfd Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 16:00:04 +0200 Subject: [PATCH 055/314] changed import --- ego/tools/io.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 7cc26c35..35e31ed9 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -17,7 +17,6 @@ from sqlalchemy import MetaData, create_engine, func from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.automap import automap_base - from geoalchemy2 import Geometry, shape # Geometry type used by SQLA from geoalchemy2 import * import geopandas as gpd from egoio.db_tables.model_draft import RenpassGisParameterRegion @@ -29,6 +28,12 @@ from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, curtailment, gen_dist, storage_distribution, plot_voltage, plot_residual_load) + from tools.results import (total_storage_charges, etrago_storages, + etrago_operating_costs, etrago_grid_investment, + edisgo_grid_investment, get_generator_investment, + investment_costs, create_etrago_results + ) + import logging logger = logging.getLogger('ego') From 5b66920a75b440e746f21a9c8165b7120a48806b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 16:00:59 +0200 Subject: [PATCH 056/314] change import --- ego/ego_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 33b7d12b..6566d2a5 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -55,7 +55,7 @@ # start eTraGo calculation eTraGo = etrago(args['eTraGo']) logger.info('Import eTraGo to eGo') - eGo = eGo(eTraGo=eTraGo, scn_name='Status Quo') + eGo = eGo(eTraGo=eTraGo, scn_name=args['eTraGo']['scn_name']) # add country code to bus and geometry (shapely) # eTraGo.buses = eTraGo.buses.drop(['country_code','geometry'], axis=1) From 1c93a3023f656f79100f9d9e070c8d4a8c266dfd Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 08:46:54 +0200 Subject: [PATCH 057/314] update file --- doc/whatsnew/v0-2-0.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index 70884b2e..53958c62 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -10,12 +10,18 @@ and is still under construction and not ready for a normal use. Added features -------------- -* Clean and restructured eGo classes and functions +* clean and restructured eGo classes and functions * add eTraGo features zo eGo * add eDisGo ... -* updated to eTraGo 0.6, eDisGo 0.2 and ego.io v0.4.2 version -* implemented pep8 style +* updated to eTraGo 0.6, eDisGo 0.2 version +* implemented pep8 style +* implemented logging for the hole model +* moved class eGo from results.py to io.py +* Using the Restfull-API for the OpenEnergy Database connection, buy using + ego.io v0.4.2. A registration is needed and can be done on + `openenergy-platform.org/login `_ +* ... Notes ----- -* +* AS an external user you need to From 2145b34e8fb9bc2a96b829d3cffb694c925d7373 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 09:24:46 +0200 Subject: [PATCH 058/314] remove function to eGo class in io.py --- ego/ego_main.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 6566d2a5..0ae5d3cc 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -20,9 +20,6 @@ if not 'READTHEDOCS' in os.environ: from etrago.appl import etrago - from tools.plots import (make_all_plots, plot_line_loading, - plot_stacked_gen, add_coordinates, curtailment, - gen_dist, storage_distribution, igeoplot) # For importing geopandas you need to install spatialindex on your system # http://github.com/libspatialindex/libspatialindex/wiki/1.-Getting-Started from tools.utilities import get_scenario_setting, get_time_steps @@ -63,6 +60,7 @@ # make a line loading plot eGo.eTraGo.plot_line_loading(eTraGo) + eGo.etrago.storage_charges # get eTraGo results form db if args['global']['recover']: From 51b24403668fabab055c594a23111088e6b6c609 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 09:24:57 +0200 Subject: [PATCH 059/314] remove function to eGo class in io.py --- ego/tools/results.py | 271 ------------------------------------------- 1 file changed, 271 deletions(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index 6d7a5e78..7cf98b10 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -23,277 +23,6 @@ if not 'READTHEDOCS' in os.environ: import pandas as pd import numpy as np - from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, - curtailment, gen_dist, - storage_distribution, - plot_voltage, plot_residual_load) - - -def total_storage_charges(network): - """ - Sum up the pysical storage values of the total scenario based on - eTraGo results. - - Parameters - ---------- - network : eTraGo Network based on pypsa.network - PyPSA Network object modified by eTraGo - - plot (bool): - Use plot function - - - Returns - ------- - - results : pandas.DataFrame - Return ... - - Notes - ----- - charge : - Quantity of charged Energy in MWh over scenario time steps - - discharge : - Quantity of discharged Energy in MWh over scenario time steps - - count : - Number of storage units - - p_nom_o_sum: - Sum of optimal installed power capacity - """ - - charge = network.storage_units_t.p[network.storage_units_t. - p[network.storage_units[network.storage_units. - p_nom_opt > 0].index].values > 0.].\ - groupby(network.storage_units.carrier, axis=1).sum().sum() - - discharge = network.storage_units_t.p[network.storage_units_t. - p[network.storage_units[network.storage_units. - p_nom_opt > 0].index].values < 0.].\ - groupby(network.storage_units.carrier, axis=1).sum().sum() - - count = network.storage_units.bus[network.storage_units.p_nom_opt > 0].\ - groupby(network.storage_units.carrier, axis=0).count() - - p_nom_sum = network.storage_units.p_nom.groupby(network.storage_units. - carrier, axis=0).sum() - - p_nom_o_sum = network.storage_units.p_nom_opt.groupby(network.storage_units. - carrier, axis=0).sum() - p_nom_o = p_nom_sum - p_nom_o_sum # Zubau - - results = pd.concat([charge.rename('charge'), discharge.rename('discharge'), - p_nom_sum, count.rename('total_units'), p_nom_o - .rename('extension'), ], axis=1, join='outer') - - return results - - -def etrago_storages(network): - """Function for storage and grid expantion costs of eTraGo. - - Parameters - ---------- - - network : eTraGo Network - eTraGo Network Class based on PyPSA - - Returns - ------- - storages : pandas.DataFrame - DataFrame with cumulated results of storages - - """ - # Charge / discharge (MWh) and installed capacity MW - storages = total_storage_charges(network=network) - - return storages - - -def etrago_operating_costs(network): - """ Function to get all operating costs of eTraGo. - - Parameters - ---------- - network : Network of eTraGo - Network of eTraGo - - Returns - ------- - power_price : :class:`~.pd.DataFrame` - - Examples - -------- - - - losses - - grid losses : amount and costs - - use calc_line_losses(network) from etrago pf_post_lopf - - ToDo - ---- - - change naming and function structure - - seperate operation costs in other functions ? - - """ - etg = network - #etg = eTraGo - # groupby v_nom - power_price = etg.generators_t.p[etg.generators[etg.generators. - control != 'Slack'].index] * etg.generators.\ - marginal_cost[etg.generators[etg.generators. - control != 'Slack'].index] # without Slack - - power_price = power_price.groupby( - etg.generators.carrier, axis=1).sum().sum() - power_price - - etg.buses_t.marginal_price - etg.buses_t['p'].sum().sum() - - # active power x nodel price / - etg.lines_t['p0'].sum().sum() - etg.lines_t['p1'].sum().sum() - # Reactive power - etg.lines_t['q0'].sum().sum() - etg.lines_t['q1'].sum().sum() - - # currency/MVA ? wie berechnen - - etg.lines_t['mu_lower'].sum().sum() - - etg.lines['s_nom'].sum() - - etg.lines_t['mu_upper'].sum().sum() - - return power_price - - -def etrago_grid_investment(network): - """ Function to get grid expantion costs form etrago - - Parameters - ---------- - - network : Network - eTraGo - - Returns - ------- - - ToDo - ---- - - add new release of etrago 0.7 - """ - - pass - - -def edisgo_grid_investment(network): - """Function to get all costs of grid investment of eDisGo. - - Notes - ----- - - ToDo add iteration and container of all costs of edisgo network - """ - pass - - -def get_generator_investment(network, scn_name): - """ Get investment costs per carrier/gernator. - - work around later db table -> check capital_cost as cost input?!? - - ToDo - ---- - - change values in csv - - add values to database - - """ - etg = network - - path = os.getcwd() - filename = 'investment_costs.csv' - invest = pd.DataFrame.from_csv(path + '/data/'+filename) - - if scn_name in ['SH Status Quo', 'Status Quo']: - invest_scn = 'Status Quo' - - if scn_name in ['SH NEP 2035', 'NEP 2035']: - invest_scn = 'NEP 2035' - - if scn_name in ['SH eGo 100', 'eGo 100']: - invest_scn = 'eGo 100' - - gen_invest = pd.concat([invest[invest_scn], - etg.generators.groupby('carrier')['p_nom'].sum()], - axis=1, join='inner') - - gen_invest = pd.concat([invest[invest_scn], etg.generators.groupby('carrier') - ['p_nom'].sum()], axis=1, join='inner') - gen_invest['carrier_costs'] = gen_invest[invest_scn] * \ - gen_invest['p_nom'] * 1000 # in MW - - return gen_invest - - -def investment_costs(network): - """ - Return pandas DataFrame with investment costs of - - etrago: - Storages - Line extentation - - edisgo: - Line extentation - Storage costs? - - ToDo - ---- - - add edisgo - - """ - etg = network - invest = pd.DataFrame() - - # storages - # get total storage investment costs - # unit of costs? - installed_storages = etg.storage_units[etg.storage_units.p_nom_opt != 0] - costs = sum(installed_storages.capital_cost * installed_storages.p_nom_opt) - invest = invest.append({'storage_costs': costs}, ignore_index=True) - - # get storage costs per voltage level - loc = etg.storage_units[etg.storage_units.p_nom_opt != 0]['bus'] - v_level = etg.buses.loc[loc, :]['v_nom'] - installed_storages = installed_storages.assign(v_nom=0) - - for i, k in v_level.iteritems(): - installed_storages.loc[installed_storages[installed_storages.bus == - i].index, 'v_nom'] = k - - storage_level = installed_storages.groupby('v_nom')['capital_cost'].sum() - - # Line extentation costs - # (eTraGo.lines.s_nom_opt - eTraGo.lines.s_nom) * eTraGo.lines.capital_cost - line_expen = (etg.lines.groupby('v_nom')['s_nom_opt'].sum() - - etg.lines.groupby('v_nom')['s_nom'].sum()) - - if line_expen.sum() <= 0: - print('Warning: !line extentation, set random costs for plotting!') - - lines_level = pd.DataFrame([[110., 722*np.exp(8)], [220., 822*np.exp(8)], - [380., 999*np.exp(9)]], columns=['v_nom', 'capital_cost']).\ - groupby('v_nom')['capital_cost'].sum() - - invest = invest.assign(line_costs=lines_level.sum()) - - # invest.transpose() - - # transfomers expantion costs - return invest def create_etrago_results(network, scn_name): From 34c2a665a12fa5cdc9be243eed2b3043d5281d55 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 09:25:13 +0200 Subject: [PATCH 060/314] remove function to eGo class in io.py --- ego/tools/io.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 35e31ed9..1c47f225 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -11,6 +11,9 @@ import sys import os +import logging +logger = logging.getLogger('ego') + if not 'READTHEDOCS' in os.environ: import pyproj as proj from shapely.geometry import Polygon, Point, MultiPolygon @@ -27,16 +30,13 @@ from egoio.tools import db from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, curtailment, gen_dist, storage_distribution, - plot_voltage, plot_residual_load) - from tools.results import (total_storage_charges, etrago_storages, - etrago_operating_costs, etrago_grid_investment, - edisgo_grid_investment, get_generator_investment, - investment_costs, create_etrago_results - ) - - -import logging -logger = logging.getLogger('ego') + plot_voltage, plot_residual_load + ) + from tools.results import (create_etrago_results) + from tools.storages import (total_storage_charges, etrago_storages) + from tools.economics import (etrago_operating_costs, etrago_grid_investment, + edisgo_grid_investment, investment_costs, + get_generator_investment) class egoBasic(): From d999e42e09f45d5b97167e135ee613e9db534b79 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 09:25:44 +0200 Subject: [PATCH 061/314] move cost functions to economics --- ego/tools/economics.py | 193 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 3 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index a8bd46bc..e1f8b535 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -1,5 +1,6 @@ """ -Module to collect useful functions for economic calculation of eGo +Module to collect useful functions for economic calculation of eGo which can +mainly distinguished in operational and investment costs. Todo: 1) Investment costs of eTrago and eDisGo @@ -7,14 +8,16 @@ """ import io -import pandas as pd import os import logging logger = logging.getLogger('ego') -# calculate annuity per time step or periode +if not 'READTHEDOCS' in os.environ: + import pandas as pd + import numpy as np +# calculate annuity per time step or periode def annuity_per_period(capex, n, wacc, t): """ Parameters @@ -37,3 +40,187 @@ def annuity_per_period(capex, n, wacc, t): # ToDo change formular to hourly annuity costs return capex * (wacc * (1 + wacc) ** n) / ((1 + wacc) ** n - 1) + + +def etrago_operating_costs(network): + """ Function to get all operating costs of eTraGo. + + Parameters + ---------- + network : Network of eTraGo + Network of eTraGo + + Returns + ------- + power_price : :class:`~.pd.DataFrame` + + Examples + -------- + + - losses + - grid losses : amount and costs + - use calc_line_losses(network) from etrago pf_post_lopf + + ToDo + ---- + - change naming and function structure + - seperate operation costs in other functions ? + + """ + etg = network + #etg = eTraGo + # groupby v_nom + power_price = etg.generators_t.p[etg.generators[etg.generators. + control != 'Slack'].index] * etg.generators.\ + marginal_cost[etg.generators[etg.generators. + control != 'Slack'].index] # without Slack + + power_price = power_price.groupby( + etg.generators.carrier, axis=1).sum().sum() + power_price + + etg.buses_t.marginal_price + etg.buses_t['p'].sum().sum() + + # active power x nodel price / + etg.lines_t['p0'].sum().sum() + etg.lines_t['p1'].sum().sum() + # Reactive power + etg.lines_t['q0'].sum().sum() + etg.lines_t['q1'].sum().sum() + + # currency/MVA ? wie berechnen + + etg.lines_t['mu_lower'].sum().sum() + + etg.lines['s_nom'].sum() + + etg.lines_t['mu_upper'].sum().sum() + + return power_price + + +def etrago_grid_investment(network): + """ Function to get grid expantion costs form etrago + + Parameters + ---------- + + network : Network + eTraGo + + Returns + ------- + + ToDo + ---- + - add new release of etrago 0.7 + """ + + pass + + +def edisgo_grid_investment(network): + """Function to get all costs of grid investment of eDisGo. + + Notes + ----- + - ToDo add iteration and container of all costs of edisgo network + """ + pass + + +def get_generator_investment(network, scn_name): + """ Get investment costs per carrier/gernator. + + work around later db table -> check capital_cost as cost input?!? + + ToDo + ---- + - change values in csv + - add values to database + + """ + etg = network + + path = os.getcwd() + filename = 'investment_costs.csv' + invest = pd.DataFrame.from_csv(path + '/data/'+filename) + + if scn_name in ['SH Status Quo', 'Status Quo']: + invest_scn = 'Status Quo' + + if scn_name in ['SH NEP 2035', 'NEP 2035']: + invest_scn = 'NEP 2035' + + if scn_name in ['SH eGo 100', 'eGo 100']: + invest_scn = 'eGo 100' + + gen_invest = pd.concat([invest[invest_scn], + etg.generators.groupby('carrier')['p_nom'].sum()], + axis=1, join='inner') + + gen_invest = pd.concat([invest[invest_scn], etg.generators.groupby('carrier') + ['p_nom'].sum()], axis=1, join='inner') + gen_invest['carrier_costs'] = gen_invest[invest_scn] * \ + gen_invest['p_nom'] * 1000 # in MW + + return gen_invest + + +def investment_costs(network): + """ + Return pandas DataFrame with investment costs of + + etrago: + Storages + Line extentation + + edisgo: + Line extentation + Storage costs? + + ToDo + ---- + - add edisgo + + """ + etg = network + invest = pd.DataFrame() + + # storages + # get total storage investment costs + # unit of costs? + installed_storages = etg.storage_units[etg.storage_units.p_nom_opt != 0] + costs = sum(installed_storages.capital_cost * installed_storages.p_nom_opt) + invest = invest.append({'storage_costs': costs}, ignore_index=True) + + # get storage costs per voltage level + loc = etg.storage_units[etg.storage_units.p_nom_opt != 0]['bus'] + v_level = etg.buses.loc[loc, :]['v_nom'] + installed_storages = installed_storages.assign(v_nom=0) + + for i, k in v_level.iteritems(): + installed_storages.loc[installed_storages[installed_storages.bus == + i].index, 'v_nom'] = k + + storage_level = installed_storages.groupby('v_nom')['capital_cost'].sum() + + # Line extentation costs + # (eTraGo.lines.s_nom_opt - eTraGo.lines.s_nom) * eTraGo.lines.capital_cost + line_expen = (etg.lines.groupby('v_nom')['s_nom_opt'].sum() + - etg.lines.groupby('v_nom')['s_nom'].sum()) + + if line_expen.sum() <= 0: + print('Warning: !line extentation, set random costs for plotting!') + + lines_level = pd.DataFrame([[110., 722*np.exp(8)], [220., 822*np.exp(8)], + [380., 999*np.exp(9)]], columns=['v_nom', 'capital_cost']).\ + groupby('v_nom')['capital_cost'].sum() + + invest = invest.assign(line_costs=lines_level.sum()) + + # invest.transpose() + + # transfomers expantion costs + return invest From 6a5ed5a93cf13087a1ee531ab7881faf4b0b104e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 09:26:28 +0200 Subject: [PATCH 062/314] introduce new file storages.py --- ego/tools/storages.py | 100 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 ego/tools/storages.py diff --git a/ego/tools/storages.py b/ego/tools/storages.py new file mode 100644 index 00000000..6f8747a0 --- /dev/null +++ b/ego/tools/storages.py @@ -0,0 +1,100 @@ +""" +This file contains the eGo functions for studies on storages. +""" + +__copyright__ = ("Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke,maltesc" + +import io +import os +import logging +logger = logging.getLogger('ego') + +if not 'READTHEDOCS' in os.environ: + import pandas as pd + import numpy as np + + +def total_storage_charges(network): + """ + Sum up the pysical storage values of the total scenario based on + eTraGo results. + + Parameters + ---------- + network : eTraGo Network based on pypsa.network + PyPSA Network object modified by eTraGo + + plot (bool): + Use plot function + + + Returns + ------- + + results : pandas.DataFrame + Return ... + + Notes + ----- + charge : + Quantity of charged Energy in MWh over scenario time steps + + discharge : + Quantity of discharged Energy in MWh over scenario time steps + + count : + Number of storage units + + p_nom_o_sum: + Sum of optimal installed power capacity + """ + + charge = network.storage_units_t.p[network.storage_units_t. + p[network.storage_units[network.storage_units. + p_nom_opt > 0].index].values > 0.].\ + groupby(network.storage_units.carrier, axis=1).sum().sum() + + discharge = network.storage_units_t.p[network.storage_units_t. + p[network.storage_units[network.storage_units. + p_nom_opt > 0].index].values < 0.].\ + groupby(network.storage_units.carrier, axis=1).sum().sum() + + count = network.storage_units.bus[network.storage_units.p_nom_opt > 0].\ + groupby(network.storage_units.carrier, axis=0).count() + + p_nom_sum = network.storage_units.p_nom.groupby(network.storage_units. + carrier, axis=0).sum() + + p_nom_o_sum = network.storage_units.p_nom_opt.groupby(network.storage_units. + carrier, axis=0).sum() + p_nom_o = p_nom_sum - p_nom_o_sum # Zubau + + results = pd.concat([charge.rename('charge'), discharge.rename('discharge'), + p_nom_sum, count.rename('total_units'), p_nom_o + .rename('extension'), ], axis=1, join='outer') + + return results + + +def etrago_storages(network): + """Function for storage and grid expantion costs of eTraGo. + + Parameters + ---------- + + network : eTraGo Network + eTraGo Network Class based on PyPSA + + Returns + ------- + storages : pandas.DataFrame + DataFrame with cumulated results of storages + + """ + # Charge / discharge (MWh) and installed capacity MW + storages = total_storage_charges(network=network) + + return storages From a67eb00e7d1560cae44f4a2a5be8ad5f0747efc3 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 09:30:09 +0200 Subject: [PATCH 063/314] add pkl data files --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 738b62ef..a0335084 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ ego/scenario_setting.json ego/noise_values.csv .idea/ noise_values.csv - +*.pkl From c4e02da3d564c81a60d3537095b784e0a99fc15a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 09:30:46 +0200 Subject: [PATCH 064/314] update file --- doc/whatsnew/v0-2-0.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index 53958c62..58e4ddb2 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -1,7 +1,7 @@ -Release v0.2.0 (April 18, 2018) -+++++++++++++++++++++++++++++++ +Release v0.2.0 (July 6, 2018) ++++++++++++++++++++++++++++++ -The third release of eGo ... +The second release of eGo ... and is still under construction and not ready for a normal use. @@ -20,6 +20,8 @@ Added features * Using the Restfull-API for the OpenEnergy Database connection, buy using ego.io v0.4.2. A registration is needed and can be done on `openenergy-platform.org/login `_ +* introduce new file storages.py +* remove functionalities from main to the eGo class * ... Notes From 86ff89ab76c18fa3bb543c90c54ecd9e861598be Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 09:59:13 +0200 Subject: [PATCH 065/314] add long_description to setup --- setup.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0c8f7410..4b693b32 100644 --- a/setup.py +++ b/setup.py @@ -7,11 +7,17 @@ __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" __author__ = "wolf_bunke" + +with open("README.rst", "r") as fh: + long_description = fh.read() + setup(name='eGo', author='wolfbunke, maltesc', author_email='', description=("A python package for distribution and transmission" "grid analysis and optimization based eDisGo and eTraGo"), + long_description=long_description, + long_description_content_type="text/x-rst", version='0.2', url='https://github.com/openego/eGo', license="GNU Affero General Public License Version 3 (AGPL-3.0)", @@ -34,7 +40,7 @@ '@dev#egg=pypsa-0.11.0fork') ], extras_require={ - 'docs': [ + 'doc': [ 'sphinx >= 1.4', 'sphinx_rtd_theme', 'sphinxcontrib-httpdomain']}, From 8b05a093e936339e2df172f03a978bb0a31ccf4a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 10:36:46 +0200 Subject: [PATCH 066/314] setup wip --- setup.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 4b693b32..264b1b82 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ "Europa-Universität Flensburg, " "Centre for Sustainable Energy Systems") __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolf_bunke" +__author__ = "wolf_bunke, maltesc" with open("README.rst", "r") as fh: @@ -45,9 +45,12 @@ 'sphinx_rtd_theme', 'sphinxcontrib-httpdomain']}, package_data={ + # If any package contains *.txt or *.rst files, include them: + '': ['*.json', '*.csv'], + # Include any *.xy files found in the 'ego' package, too: 'ego': [ - os.path.join('*.json'), + '*.json', os.path.join('tools', '*.json'), - os.path.join('data', '*.csv')] + os.path.join('data', '*.csv'), ] } ) From 2e92d41ae220593c1694d630917017cc8d66dd6a Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Tue, 3 Jul 2018 10:47:58 +0200 Subject: [PATCH 067/314] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index af647a44..5ff42ef6 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ :target: http://openego.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status -.. image:: (https://openegoproject.files.wordpress.com/2017/02/ +.. image:: (https://openegoproject.files.wordpress.com/2017/02/\ open_ego_logo_breit.png?w=400) eGo From 079e268c782326a23a05fccc18cf4543828364f8 Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Tue, 3 Jul 2018 10:48:17 +0200 Subject: [PATCH 068/314] Update README.rst --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 5ff42ef6..ae4a8421 100644 --- a/README.rst +++ b/README.rst @@ -2,8 +2,8 @@ :target: http://openego.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status -.. image:: (https://openegoproject.files.wordpress.com/2017/02/\ - open_ego_logo_breit.png?w=400) +.. image:: ("https://openegoproject.files.wordpress.com/2017/02/" + "open_ego_logo_breit.png?w=400") eGo ==== From ab1d90a1a808ffb8048756ba2571acd30ee4e0a2 Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Tue, 3 Jul 2018 10:48:49 +0200 Subject: [PATCH 069/314] Update README.rst --- README.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.rst b/README.rst index ae4a8421..b8ed6275 100644 --- a/README.rst +++ b/README.rst @@ -2,8 +2,7 @@ :target: http://openego.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status -.. image:: ("https://openegoproject.files.wordpress.com/2017/02/" - "open_ego_logo_breit.png?w=400") +.. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 eGo ==== From ce5c3029bb70b84307f8e8c17c01027072cfec8c Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Tue, 3 Jul 2018 10:49:09 +0200 Subject: [PATCH 070/314] Update README.rst --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index b8ed6275..7f332654 100644 --- a/README.rst +++ b/README.rst @@ -26,8 +26,8 @@ Create a virtualenvironment (where you like it) and activate it: $ virtualenv eGo --clear -p python3.5 $ source venv/bin/activate - $ (pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo - --process-dependency-links) + $ pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo + --process-dependency-links Copyleft From b6ce80c9f698e7396a09094b0ebca081502efa54 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 11:06:29 +0200 Subject: [PATCH 071/314] update docs --- doc/api.rst | 2 +- doc/api/ego.tools.rst | 8 ++++++++ doc/developer.rst | 6 +++++- doc/getting_started.rst | 3 ++- doc/index.rst | 2 +- doc/usage_details.rst | 4 ++-- doc/welcome.rst | 9 +++++---- doc/whatsnew.rst | 2 +- 8 files changed, 25 insertions(+), 11 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index 83b7a11a..3ffe4d26 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -3,6 +3,6 @@ .. toctree:: :maxdepth: 7 :glob: - :titlesonly: + API diff --git a/doc/api/ego.tools.rst b/doc/api/ego.tools.rst index 67d915df..d018e051 100644 --- a/doc/api/ego.tools.rst +++ b/doc/api/ego.tools.rst @@ -44,6 +44,14 @@ ego\.tools\.specs :members: :undoc-members: :show-inheritance: + +ego\.tools\.storages +----------------- + +.. automodule:: ego.tools.storages + :members: + :undoc-members: + :show-inheritance: ego\.tools\.utilities module ---------------------------- diff --git a/doc/developer.rst b/doc/developer.rst index c0bdce24..11a0a144 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -1,5 +1,9 @@ +=============== Developer notes -~~~~~~~~~~~~~~~ +=============== + + + diff --git a/doc/getting_started.rst b/doc/getting_started.rst index 5628ae13..b00b5c20 100644 --- a/doc/getting_started.rst +++ b/doc/getting_started.rst @@ -1,5 +1,6 @@ +=============== Getting started -############### +=============== .. warning:: diff --git a/doc/index.rst b/doc/index.rst index 27b6d930..9a2cb99c 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,3 +1,4 @@ +============================= Welcome to eGo documentation! ============================= @@ -12,7 +13,6 @@ Welcome to eGo documentation! .. toctree:: :maxdepth: 7 - :titlesonly: welcome getting_started diff --git a/doc/usage_details.rst b/doc/usage_details.rst index 0aae78be..84ad885e 100644 --- a/doc/usage_details.rst +++ b/doc/usage_details.rst @@ -1,6 +1,6 @@ - +=============== How to use eGo? -~~~~~~~~~~~~~~~~~~ +=============== Examples diff --git a/doc/welcome.rst b/doc/welcome.rst index f24b0233..3d4c8ef1 100644 --- a/doc/welcome.rst +++ b/doc/welcome.rst @@ -1,6 +1,6 @@ -############ +============ The eGo tool -############ +============ The python package eGo is a toolbox and application which connects the tool eTraGo with a Optimization of flexibility options for transmission grids based on PyPSA @@ -9,7 +9,8 @@ packages are part of the research project `open_eGo Date: Tue, 3 Jul 2018 13:38:04 +0200 Subject: [PATCH 072/314] update setup for file import --- MANIFEST.in | 10 ++++++++++ setup.py | 21 +++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..2655a200 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,10 @@ +include README.rst +include LICENSE +include *txt +include MANIFEST.in +include *.json +include *.rst +include *.csv +include ego/scenario_setting.json +include ego/data/*.csv +include ego/tools/*.json diff --git a/setup.py b/setup.py index 264b1b82..1e93b153 100644 --- a/setup.py +++ b/setup.py @@ -8,20 +8,22 @@ __author__ = "wolf_bunke, maltesc" -with open("README.rst", "r") as fh: - long_description = fh.read() +def read(fname): + return open(os.path.join(os.path.dirname(__file__), fname)).read() + setup(name='eGo', + version='0.2', author='wolfbunke, maltesc', author_email='', description=("A python package for distribution and transmission" "grid analysis and optimization based eDisGo and eTraGo"), - long_description=long_description, + long_description=read('README.rst'), long_description_content_type="text/x-rst", - version='0.2', url='https://github.com/openego/eGo', license="GNU Affero General Public License Version 3 (AGPL-3.0)", packages=find_packages(), + package_dir={'ego': 'ego'}, include_package_data=True, install_requires=['egoio == 0.4.1', 'eDisGo == 0.0.2', @@ -45,12 +47,7 @@ 'sphinx_rtd_theme', 'sphinxcontrib-httpdomain']}, package_data={ - # If any package contains *.txt or *.rst files, include them: - '': ['*.json', '*.csv'], - # Include any *.xy files found in the 'ego' package, too: - 'ego': [ - '*.json', - os.path.join('tools', '*.json'), - os.path.join('data', '*.csv'), ] - } + 'ego': [os.path.join('tools/', '*.csv')], + 'ego.data': ['/*.csv'] + }, ) From be0e2ffd9affd51131da66011ffcb3de435daf76 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 3 Jul 2018 14:27:21 +0200 Subject: [PATCH 073/314] update file --- setup.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 1e93b153..57d29ac6 100644 --- a/setup.py +++ b/setup.py @@ -25,16 +25,16 @@ def read(fname): packages=find_packages(), package_dir={'ego': 'ego'}, include_package_data=True, - install_requires=['egoio == 0.4.1', - 'eDisGo == 0.0.2', - 'eTraGo == 0.6', - 'pandas ==0.20.3', + install_requires=['egoio==0.4.1', + 'eDisGo==0.0.2', + 'eTraGo==0.6', + 'pandas==0.20.3', 'pypsa==0.11.0fork', - 'sqlalchemy >= 1.0.15, <= 1.2.0', - 'geoalchemy2 >= 0.3.0, <=0.4.0', - 'pyproj == 1.9.5.1', + 'sqlalchemy>= 1.0.15, <=1.2.0', + 'geoalchemy2>= 0.3.0, <=0.4.0', + 'pyproj==1.9.5.1', 'geopandas==0.3.0', - 'matplotlib >= 1.5.3, <=1.5.3', + 'matplotlib>= 1.5.3, <=1.5.3', 'Rtree==0.8.3', 'plotly==2.2.3' ], From cd59dffe47fb0e5a5fb0afb6d25f7192aa2223b7 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 4 Jul 2018 17:03:32 +0200 Subject: [PATCH 074/314] implement new class structure --- ego/tools/io.py | 137 +++++++++++++++++++++++++++++-------------- ego/tools/results.py | 1 + 2 files changed, 94 insertions(+), 44 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 1c47f225..4134967d 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -16,17 +16,14 @@ if not 'READTHEDOCS' in os.environ: import pyproj as proj + import geopandas as gpd + import pandas as pd + import numpy as np from shapely.geometry import Polygon, Point, MultiPolygon - from sqlalchemy import MetaData, create_engine, func + from sqlalchemy import MetaData, create_engine, and_, func from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.automap import automap_base from geoalchemy2 import * - import geopandas as gpd - from egoio.db_tables.model_draft import RenpassGisParameterRegion - from egoio.db_tables import model_draft, grid - from sqlalchemy import and_, func - import pandas as pd - import numpy as np from egoio.tools import db from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, curtailment, gen_dist, storage_distribution, @@ -37,38 +34,77 @@ from tools.economics import (etrago_operating_costs, etrago_grid_investment, edisgo_grid_investment, investment_costs, get_generator_investment) + from tools.utilities import get_scenario_setting, get_time_steps + from etrago.appl import etrago + from egoio.db_tables.model_draft import RenpassGisParameterRegion + from egoio.db_tables import model_draft, grid + +class egoBasic(object): + """The eGo basic class creates based on your scenario_setting.json file + the ... -class egoBasic(): - """eGo basics class. Parameters ---------- + jsonpath : json + Path to _scenario_setting.json_ file. - eTraGo : Network + Results + ------- + eTraGo : pandas.DataFrame of PyPSA Network container of eTraGo based on PyPSA - eDisGo : Network + eDisGo : pandas.DataFrame of PyPSA Network container of eDisGo based on PyPSA - args : dict + json_file : dict Dict of the scenario_setting.json + session : sqlalchemy + Database session for the oedb connection. """ - def __init__(self, eTraGo, *args, **kwargs): + def __init__(self, + jsonpath, * args, **kwargs): # eTraGo=None + + self.jsonpath = 'scenario_setting.json' + self.json_file = get_scenario_setting(self.jsonpath) + + #self.etrago_network = None + self.edisgo_network = None + + # Database connection from json_file + try: + conn = db.connection(section=self.json_file['global']['db']) + Session = sessionmaker(bind=conn) + self.session = Session() + logger.info('Connected to Database') + except: + logger.error('Failed connection to Database', exc_info=True) - self.eTraGo = eTraGo - self.eDisGo = None - self.scn_name = kwargs.get('scn_name', 'Status Quo') + # get scn_name + self.scn_name = self.json_file['eTraGo']['scn_name'] + + if self.json_file['global']['eTraGo'] is True: + logger.info('Create eTraGo network') + self.etrago_network = etrago(self.json_file['eTraGo']) + + if self.json_file['global']['eDisGo'] is True: + logger.info('Create eDisGo network') + self.edisgo_network = None # add eDisGo initialisation here + + pass def __repr__(self): r = ('eGoResults is created.') - if not self.eTraGo: + if not self.etrago_network: r += "\nThe results does not incluede eTraGo results" - if not self.eDisGo: + if not self.edisgo_network: r += "\nThe results does not incluede eDisGo results" return r + pass + class eTraGoResults(egoBasic): """eTraGo Results @@ -92,31 +128,41 @@ class eTraGoResults(egoBasic): eTraGo Documentation. """ - def __init__(self, eTraGo, *args, **kwargs): - super().__init__(eTraGo, *args, **kwargs) - self.scn_name = kwargs.get('scn_name', 'Status Quo') + def __init__(self, jsonpath, *args, **kwargs): + """ + """ + super(eTraGoResults, self).__init__(self, jsonpath, + *args, **kwargs) + + #self.etrago_network = etrago_network self.etrago = pd.DataFrame() - self.etrago.gernator = None - self.etrago.storage_charges = total_storage_charges(eTraGo) - self.etrago.storage_costs = etrago_storages(eTraGo) - self.etrago.operating_costs = etrago_operating_costs(eTraGo) + self.etrago.generator = pd.DataFrame() + self.etrago.storage_charges = total_storage_charges(self.etrago_network) + self.etrago.storage_costs = etrago_storages(self.etrago_network) + self.etrago.operating_costs = etrago_operating_costs( + self.etrago_network) # methods imported from eTraGo - eTraGo.plot_line_loading = plot_line_loading + self.etrago_network.plot_line_loading = plot_line_loading + + self.etrago_network.plot_stacked_gen = plot_stacked_gen - eTraGo.plot_stacked_gen = plot_stacked_gen + self.etrago_network.curtailment = curtailment - eTraGo.curtailment = curtailment + self.etrago_network.gen_dist = gen_dist - eTraGo.gen_dist = gen_dist + self.etrago_network.storage_distribution = storage_distribution - eTraGo.storage_distribution = storage_distribution + self.etrago_network.plot_voltage = plot_voltage - eTraGo.plot_voltage = plot_voltage + self.etrago_network.plot_residual_load = plot_residual_load - eTraGo.plot_residual_load = plot_residual_load + self.etrago.generator = create_etrago_results(self.etrago_network, + self.scn_name) - #self.etrago.gernator = create_etrago_results(eTraGo, scn_name) + # add here etrago_from_oedb + + pass class eDisGoResults(egoBasic): @@ -131,14 +177,16 @@ class eDisGoResults(egoBasic): """ - def __init__(self, eDisGo): - super().__init__(eDisGo) + def __init__(self, jsonpath, *args, **kwargs): + super(eDisGoResults, self).__init__(self, jsonpath, + *args, **kwargs) + self.edisgo = pd.DataFrame() - pass + pass -class eGo(eTraGoResults): +class eGo(eTraGoResults, eDisGoResults): """Main eGo module which including all results and main functionalities. @@ -148,22 +196,24 @@ class eGo(eTraGoResults): eDisGo : Network - - ToDo ---- - add eDisGo """ - def __init__(self, eTraGo, scn_name): - super().__init__(eTraGo, scn_name) + def __init__(self, jsonpath, *args, **kwargs): + super(eGo, self).__init__(self, jsonpath, + *args, **kwargs) + # super().__init__(eDisGo) self.total = pd.DataFrame() # add total results here + # add all ego function + pass + # write_results_to_db(): logging.info('Initialisation of eGo Results') - pass def geolocation_buses(network, session): @@ -197,8 +247,7 @@ def geolocation_buses(network, session): # map to classes Base = automap_base(metadata=meta) Base.prepare() - RenpassGISRegion = \ - Base.classes.renpass_gis_parameter_region + RenpassGISRegion = Base.classes.renpass_gis_parameter_region # Define regions region_id = ['DE', 'DK', 'FR', 'BE', 'LU', diff --git a/ego/tools/results.py b/ego/tools/results.py index 7cf98b10..97d88b1b 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -23,6 +23,7 @@ if not 'READTHEDOCS' in os.environ: import pandas as pd import numpy as np + from tools.economics import get_generator_investment def create_etrago_results(network, scn_name): From 49bf48ce5bb7477a769b1275a461cfa168e66e69 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 4 Jul 2018 17:04:27 +0200 Subject: [PATCH 075/314] add test file for classes --- ego/test_ego.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 ego/test_ego.py diff --git a/ego/test_ego.py b/ego/test_ego.py new file mode 100644 index 00000000..6d84fb24 --- /dev/null +++ b/ego/test_ego.py @@ -0,0 +1,37 @@ +from tools.io import eGo, egoBasic, eDisGoResults, eTraGoResults + + +c = egoBasic(jsonpath='scenario_setting.json') + +c.edisgo_network +c.etrago_network + +b = eTraGoResults(jsonpath='scenario_setting.json') + + +b.etrago_network.plot_line_loading +b.etrago_network.plot_line_loading(b.etrago_network) +b.etrago.storage_charges + + +ego = eGo(jsonpath='scenario_setting.json') + +ego.etrago.storage_charges +ego.etrago_network.buses +ego + + +""" +Ausbau: +ego = eGo(jsonpath='scenario_setting.json') + + + +ego.etrago_network # Original eTraGo Network Klasse +ego.etrago.storage_charges # Aggregierte eGo Ergebnisse für etrago +ego.edisgo_network # Original eDisGo Network Klasse ??? +ego.edisgo # Aggregierte eGo Ergebnisse für edisgo +ego.total # eGo gesamt Ergebnisse über alle Spannungsebenen + + +""" From e04dc75f893fafaca5a5e5ab8b559b0d4abda7eb Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 4 Jul 2018 17:09:34 +0200 Subject: [PATCH 076/314] update main, move old eTraGo functions --- ego/ego_main.py | 45 ++++++++++++--------------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 0ae5d3cc..c1f1ae14 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -19,15 +19,8 @@ import logging if not 'READTHEDOCS' in os.environ: - from etrago.appl import etrago - # For importing geopandas you need to install spatialindex on your system - # http://github.com/libspatialindex/libspatialindex/wiki/1.-Getting-Started - from tools.utilities import get_scenario_setting, get_time_steps - from tools.io import geolocation_buses, etrago_from_oedb from tools.io import eGo - from sqlalchemy.orm import sessionmaker - from egoio.tools import db - from etrago.tools.io import results_to_oedb + #from etrago.tools.io import results_to_oedb from tools.utilities import define_logging logger = define_logging(log_name='ego.log') @@ -36,34 +29,20 @@ # import scenario settings **args of eTraGo logger.info('Start calculation') - args = get_scenario_setting(json_file='scenario_setting.json') - logger.info("calculation settings are used \ - with Metadata: \n %s" % args) - - try: - conn = db.connection(section=args['global']['db']) - Session = sessionmaker(bind=conn) - session = Session() - except OperationalError: - logger.error('Failed connection to Database', exc_info=True) - - # start calculations of eTraGo if true - if args['global']['eTraGo']: - # start eTraGo calculation - eTraGo = etrago(args['eTraGo']) - logger.info('Import eTraGo to eGo') - eGo = eGo(eTraGo=eTraGo, scn_name=args['eTraGo']['scn_name']) - - # add country code to bus and geometry (shapely) - # eTraGo.buses = eTraGo.buses.drop(['country_code','geometry'], axis=1) - # test = geolocation_buses(network = eTraGo, session) - - # make a line loading plot - eGo.eTraGo.plot_line_loading(eTraGo) - eGo.etrago.storage_charges + + ego = eGo(jsonpath='scenario_setting.json') + + ego.etrago.storage_charges + ego.etrago_network.buses + ego + + # add country code to bus and geometry (shapely) + # eTraGo.buses = eTraGo.buses.drop(['country_code','geometry'], axis=1) + # test = geolocation_buses(network = eTraGo, session) # get eTraGo results form db if args['global']['recover']: + # TODO add it to class eTraGo = etrago_from_oedb(session, args) # use eTraGo results from ego calculations if true From 4c5f2b69c677a0691d98d61f587105a0e94732a7 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 09:57:32 +0200 Subject: [PATCH 077/314] add eTrago plot functions --- ego/ego_main.py | 31 ++++++++++++++++++++--- ego/tools/io.py | 66 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 78 insertions(+), 19 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index c1f1ae14..cec48029 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -27,14 +27,14 @@ if __name__ == '__main__': - # import scenario settings **args of eTraGo + # import scenario settings **args of eTraGo logger.info('Start calculation') ego = eGo(jsonpath='scenario_setting.json') - ego.etrago.storage_charges - ego.etrago_network.buses - ego + print(ego.etrago.storage_charges) + ego.etrago_network.plot() +""" # add country code to bus and geometry (shapely) # eTraGo.buses = eTraGo.buses.drop(['country_code','geometry'], axis=1) @@ -143,3 +143,26 @@ # possible aggregation of results # exports: total system costs, plots, csv export files + +""" +""" +# Using graphviz for Calculation Dokumentation. + +from pycallgraph import PyCallGraph +from pycallgraph.output import GraphvizOutput + +def main(): + graphviz = GraphvizOutput() + graphviz.output_file = 'basic.png' + + with PyCallGraph(output=graphviz): + logger.info('Start calculation') + + ego = eGo(jsonpath='scenario_setting.json') + + print(ego.etrago.storage_charges) + ego.etrago_network.plot() + +if __name__ == '__main__': + main() +""" diff --git a/ego/tools/io.py b/ego/tools/io.py index 4134967d..898166db 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -69,7 +69,7 @@ def __init__(self, self.jsonpath = 'scenario_setting.json' self.json_file = get_scenario_setting(self.jsonpath) - #self.etrago_network = None + # self.etrago_network = None self.edisgo_network = None # Database connection from json_file @@ -134,35 +134,71 @@ def __init__(self, jsonpath, *args, **kwargs): super(eTraGoResults, self).__init__(self, jsonpath, *args, **kwargs) - #self.etrago_network = etrago_network + # add selected results to Results container self.etrago = pd.DataFrame() self.etrago.generator = pd.DataFrame() self.etrago.storage_charges = total_storage_charges(self.etrago_network) self.etrago.storage_costs = etrago_storages(self.etrago_network) self.etrago.operating_costs = etrago_operating_costs( self.etrago_network) + self.etrago.generator = create_etrago_results(self.etrago_network, + self.scn_name) + # add functions direct + #self.etrago_network.etg_line_loading = etg_line_loading - # methods imported from eTraGo - self.etrago_network.plot_line_loading = plot_line_loading - - self.etrago_network.plot_stacked_gen = plot_stacked_gen + pass - self.etrago_network.curtailment = curtailment + # include eTraGo functions and methods + def etrago_line_loading(self, **kwargs): + """ + Integrate and use function from eTraGo. + For more information see: + """ + return plot_line_loading(network=self.etrago_network, **kwargs) - self.etrago_network.gen_dist = gen_dist + def etrago_stacked_gen(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return plot_stacked_gen(network=self.etrago_network, **kwargs) - self.etrago_network.storage_distribution = storage_distribution + def etrago_curtailment(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return curtailment(network=self.etrago_network, **kwargs) - self.etrago_network.plot_voltage = plot_voltage + def etrago_gen_dist(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return gen_dist(network=self.etrago_network, **kwargs) - self.etrago_network.plot_residual_load = plot_residual_load + def etrago_storage_distribution(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return storage_distribution(network=self.etrago_network, **kwargs) - self.etrago.generator = create_etrago_results(self.etrago_network, - self.scn_name) + def etrago_voltage(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return plot_voltage(network=self.etrago_network, **kwargs) - # add here etrago_from_oedb + def etrago_residual_load(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return plot_residual_load(network=self.etrago_network, **kwargs) - pass + # add other methods from eTraGo here class eDisGoResults(egoBasic): From 272f152c3db92baaedd828c193079a5e70a9ae25 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 10:29:10 +0200 Subject: [PATCH 078/314] changed io --- ego/scenario_setting.json | 2 +- ego/test_ego.py | 34 ++++++++++++++++------------------ ego/tools/io.py | 5 ++--- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index c4f351b4..ad2c2fec 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -13,7 +13,7 @@ "method": "lopf", "pf_post_lopf": false, "start_snapshot": 1, - "end_snapshot" : 5, + "end_snapshot" : 2, "solver": "gurobi", "solver_options":{}, "scn_name": "NEP 2035", diff --git a/ego/test_ego.py b/ego/test_ego.py index 6d84fb24..cefc6ffa 100644 --- a/ego/test_ego.py +++ b/ego/test_ego.py @@ -1,24 +1,11 @@ -from tools.io import eGo, egoBasic, eDisGoResults, eTraGoResults - - -c = egoBasic(jsonpath='scenario_setting.json') - -c.edisgo_network -c.etrago_network - -b = eTraGoResults(jsonpath='scenario_setting.json') - - -b.etrago_network.plot_line_loading -b.etrago_network.plot_line_loading(b.etrago_network) -b.etrago.storage_charges - +from tools.io import eGo ego = eGo(jsonpath='scenario_setting.json') -ego.etrago.storage_charges -ego.etrago_network.buses -ego +ego.etrago_line_loading() +ego.etrago_network.plot() + +ego.edisgo_network """ @@ -35,3 +22,14 @@ """ +c = egoBasic(jsonpath='scenario_setting.json') + +c.edisgo_network +c.etrago_network + +b = eTraGoResults(jsonpath='scenario_setting.json') + + +b.etrago_network.plot_line_loading +b.etrago_network.plot_line_loading(b.etrago_network) +b.etrago.storage_charges diff --git a/ego/tools/io.py b/ego/tools/io.py index 898166db..0be01553 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -144,7 +144,7 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago.generator = create_etrago_results(self.etrago_network, self.scn_name) # add functions direct - #self.etrago_network.etg_line_loading = etg_line_loading + #self.etrago_network.etrago_line_loading = etrago_line_loading pass @@ -214,8 +214,7 @@ class eDisGoResults(egoBasic): """ def __init__(self, jsonpath, *args, **kwargs): - super(eDisGoResults, self).__init__(self, jsonpath, - *args, **kwargs) + super(eDisGoResults, self).__init__(self, jsonpath, *args, **kwargs) self.edisgo = pd.DataFrame() From 930476ca8b95b8cb402e1034e100e4bac95d5b9e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 11:01:00 +0200 Subject: [PATCH 079/314] remove multiple parameter --- ego/scenario_setting.json | 2 -- ego/tools/utilities.py | 21 ++++++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index ad2c2fec..4ced8a1c 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -8,8 +8,6 @@ "gridversion": "v0.4.2" }, "eTraGo": { - "db": "oedb", - "gridversion": "v0.4.2", "method": "lopf", "pf_post_lopf": false, "start_snapshot": 1, diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index 5375340e..68de2a5d 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -7,6 +7,7 @@ import json import logging + __copyright__ = ("Flensburg University of Applied Sciences, " "Europa-Universität Flensburg, " "Centre for Sustainable Energy Systems") @@ -42,7 +43,11 @@ def define_logging(log_name='ego.log'): return ego_logger +logger = define_logging(log_name='ego.log') + # import scenario settings **args + + def get_scenario_setting(json_file='scenario_setting.json'): """ Get and open json file with scenaio settings of eGo @@ -55,17 +60,27 @@ def get_scenario_setting(json_file='scenario_setting.json'): """ path = os.getcwd() # add try ego/ - print(path) + print("Your path is:\n", path) + with open(path + '/'+json_file) as f: scn_set = json.load(f) if scn_set['global'].get('eTraGo') == True: - print('Use eTraGo settings') + + print('Using and importing eTraGo settings') + + # special case of SH and model_draft + # ToDo: check and maybe remove this part sh_scen = ["SH Status Quo", "SH NEP 2035", "SH eGo 100"] if scn_set['eTraGo'].get('scn_name') in sh_scen and scn_set['eTraGo'].\ - get('gridversion') == "v0.3.0": + get('gridversion') == "v0.4.2": scn_set['eTraGo']['gridversion'] = None + # add global parameter to eTraGo scn_set + scn_set['eTraGo'].update({'db': scn_set['global'].get('db')}) + scn_set['eTraGo'].update( + {'gridversion': scn_set['global'].get('gridversion')}) + if scn_set['global'].get('eDisGo') == True: print('Use eDisGo settings') From 99fe4b19268839a1807852fc75412923e8e428c5 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 11:03:49 +0200 Subject: [PATCH 080/314] chage logger for RTD --- ego/ego_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index cec48029..6f57c2b4 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -21,8 +21,8 @@ if not 'READTHEDOCS' in os.environ: from tools.io import eGo #from etrago.tools.io import results_to_oedb - from tools.utilities import define_logging +from tools.utilities import define_logging logger = define_logging(log_name='ego.log') if __name__ == '__main__': From 8d341efc56c1018723414107f63b082a0cf143c9 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 11:30:11 +0200 Subject: [PATCH 081/314] update io for rtd test --- ego/tools/io.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 0be01553..f5a367a9 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -163,12 +163,12 @@ def etrago_stacked_gen(self, **kwargs): """ return plot_stacked_gen(network=self.etrago_network, **kwargs) - def etrago_curtailment(self, **kwargs): - """ - Integrate function from eTraGo. - For more information see: - """ - return curtailment(network=self.etrago_network, **kwargs) + # def etrago_curtailment(self, **kwargs): + # """ + # Integrate function from eTraGo. + # For more information see: + # """ + # return curtailment(network=self.etrago_network, **kwargs) def etrago_gen_dist(self, **kwargs): """ From 287957d3af18342c8e01c83d39e1ef01267ca33a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 11:33:25 +0200 Subject: [PATCH 082/314] comment functions for rtd --- ego/tools/io.py | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index f5a367a9..2f7b83db 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -170,33 +170,33 @@ def etrago_stacked_gen(self, **kwargs): # """ # return curtailment(network=self.etrago_network, **kwargs) - def etrago_gen_dist(self, **kwargs): - """ - Integrate function from eTraGo. - For more information see: - """ - return gen_dist(network=self.etrago_network, **kwargs) + # def etrago_gen_dist(self, **kwargs): + # """ + # Integrate function from eTraGo. + # For more information see: + # """ + # return gen_dist(network=self.etrago_network, **kwargs) - def etrago_storage_distribution(self, **kwargs): - """ - Integrate function from eTraGo. - For more information see: - """ - return storage_distribution(network=self.etrago_network, **kwargs) + # def etrago_storage_distribution(self, **kwargs): + # """ + # Integrate function from eTraGo. + # For more information see: + # """ + # return storage_distribution(network=self.etrago_network, **kwargs) - def etrago_voltage(self, **kwargs): - """ - Integrate function from eTraGo. - For more information see: - """ - return plot_voltage(network=self.etrago_network, **kwargs) + # def etrago_voltage(self, **kwargs): + # """ + # Integrate function from eTraGo. + # For more information see: + # """ + # return plot_voltage(network=self.etrago_network, **kwargs) - def etrago_residual_load(self, **kwargs): - """ - Integrate function from eTraGo. - For more information see: - """ - return plot_residual_load(network=self.etrago_network, **kwargs) + # def etrago_residual_load(self, **kwargs): + # """ + # Integrate function from eTraGo. + # For more information see: + # """ + # return plot_residual_load(network=self.etrago_network, **kwargs) # add other methods from eTraGo here From 6355a291fa1a9687f3935b817c3592592f260559 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 12:58:36 +0200 Subject: [PATCH 083/314] comment functions --- ego/tools/io.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 2f7b83db..33026dc5 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -149,19 +149,19 @@ def __init__(self, jsonpath, *args, **kwargs): pass # include eTraGo functions and methods - def etrago_line_loading(self, **kwargs): - """ - Integrate and use function from eTraGo. - For more information see: - """ - return plot_line_loading(network=self.etrago_network, **kwargs) + # def etrago_line_loading(self, **kwargs): + # """ + # Integrate and use function from eTraGo. + # For more information see: + # """ + # return plot_line_loading(network=self.etrago_network, **kwargs) - def etrago_stacked_gen(self, **kwargs): - """ - Integrate function from eTraGo. - For more information see: - """ - return plot_stacked_gen(network=self.etrago_network, **kwargs) + # def etrago_stacked_gen(self, **kwargs): + # """ + # Integrate function from eTraGo. + # For more information see: + # """ + # return plot_stacked_gen(network=self.etrago_network, **kwargs) # def etrago_curtailment(self, **kwargs): # """ From d096c64eb3e7159dbbd7ad91b54f975c6ade80fe Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:05:57 +0200 Subject: [PATCH 084/314] change structure for rtd --- ego/tools/io.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 33026dc5..65382739 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -24,20 +24,21 @@ from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.automap import automap_base from geoalchemy2 import * - from egoio.tools import db - from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, - curtailment, gen_dist, storage_distribution, - plot_voltage, plot_residual_load - ) - from tools.results import (create_etrago_results) - from tools.storages import (total_storage_charges, etrago_storages) - from tools.economics import (etrago_operating_costs, etrago_grid_investment, - edisgo_grid_investment, investment_costs, - get_generator_investment) - from tools.utilities import get_scenario_setting, get_time_steps - from etrago.appl import etrago - from egoio.db_tables.model_draft import RenpassGisParameterRegion - from egoio.db_tables import model_draft, grid + +from egoio.tools import db +from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, + curtailment, gen_dist, storage_distribution, + plot_voltage, plot_residual_load + ) +from tools.results import (create_etrago_results) +from tools.storages import (total_storage_charges, etrago_storages) +from tools.economics import (etrago_operating_costs, etrago_grid_investment, + edisgo_grid_investment, investment_costs, + get_generator_investment) +from tools.utilities import get_scenario_setting, get_time_steps +from etrago.appl import etrago +from egoio.db_tables.model_draft import RenpassGisParameterRegion +from egoio.db_tables import model_draft, grid class egoBasic(object): From d5ee947a5034ebdddfc05c8ef785a0bc488a5067 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:20:14 +0200 Subject: [PATCH 085/314] change structure for rtd --- ego/tools/io.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 65382739..7a6d2e5b 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -13,18 +13,8 @@ import os import logging logger = logging.getLogger('ego') - -if not 'READTHEDOCS' in os.environ: - import pyproj as proj - import geopandas as gpd - import pandas as pd - import numpy as np - from shapely.geometry import Polygon, Point, MultiPolygon - from sqlalchemy import MetaData, create_engine, and_, func - from sqlalchemy.orm import sessionmaker - from sqlalchemy.ext.automap import automap_base - from geoalchemy2 import * - +import pandas as pd +import numpy as np from egoio.tools import db from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, curtailment, gen_dist, storage_distribution, @@ -40,25 +30,35 @@ from egoio.db_tables.model_draft import RenpassGisParameterRegion from egoio.db_tables import model_draft, grid +if not 'READTHEDOCS' in os.environ: + import pyproj as proj + import geopandas as gpd -class egoBasic(object): - """The eGo basic class creates based on your scenario_setting.json file - the ... + from shapely.geometry import Polygon, Point, MultiPolygon + from sqlalchemy import MetaData, create_engine, and_, func + from sqlalchemy.orm import sessionmaker + from sqlalchemy.ext.automap import automap_base + from geoalchemy2 import * +class egoBasic(object): + """The eGo basic class select and creates based on your + `scenario_setting.json` file your definde eTraGo and + eDisGo results container. + Parameters ---------- - jsonpath : json + jsonpath : :obj:`json` Path to _scenario_setting.json_ file. Results ------- - eTraGo : pandas.DataFrame of PyPSA + eTraGo : :pandas:`pandas.Dataframe` of PyPSA Network container of eTraGo based on PyPSA - eDisGo : pandas.DataFrame of PyPSA + eDisGo : :pandas:`pandas.Dataframe` of PyPSA Network container of eDisGo based on PyPSA json_file : dict - Dict of the scenario_setting.json + Dict of the scenario_setting.json file session : sqlalchemy Database session for the oedb connection. From d0852e088ad7d7158294677479fba0ab88094264 Mon Sep 17 00:00:00 2001 From: WolfBunke Date: Thu, 5 Jul 2018 13:21:02 +0200 Subject: [PATCH 086/314] Update README.rst --- README.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.rst b/README.rst index af647a44..b8ed6275 100644 --- a/README.rst +++ b/README.rst @@ -2,8 +2,7 @@ :target: http://openego.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status -.. image:: (https://openegoproject.files.wordpress.com/2017/02/ - open_ego_logo_breit.png?w=400) +.. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 eGo ==== From 8726236675c060f90e8e834b85e70106d91e57ad Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:22:31 +0200 Subject: [PATCH 087/314] change structure for rtd --- ego/tools/io.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 7a6d2e5b..63f17110 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -150,12 +150,12 @@ def __init__(self, jsonpath, *args, **kwargs): pass # include eTraGo functions and methods - # def etrago_line_loading(self, **kwargs): - # """ - # Integrate and use function from eTraGo. - # For more information see: - # """ - # return plot_line_loading(network=self.etrago_network, **kwargs) + def etrago_line_loading(self, **kwargs): + """ + Integrate and use function from eTraGo. + For more information see: + """ + return plot_line_loading(network=self.etrago_network, **kwargs) # def etrago_stacked_gen(self, **kwargs): # """ From 4d937bab98722009f73437bd2b24ad0630be981f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:29:30 +0200 Subject: [PATCH 088/314] change structure for rtd --- ego/tools/io.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 63f17110..b6b37c43 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -15,20 +15,7 @@ logger = logging.getLogger('ego') import pandas as pd import numpy as np -from egoio.tools import db -from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, - curtailment, gen_dist, storage_distribution, - plot_voltage, plot_residual_load - ) -from tools.results import (create_etrago_results) -from tools.storages import (total_storage_charges, etrago_storages) -from tools.economics import (etrago_operating_costs, etrago_grid_investment, - edisgo_grid_investment, investment_costs, - get_generator_investment) -from tools.utilities import get_scenario_setting, get_time_steps -from etrago.appl import etrago -from egoio.db_tables.model_draft import RenpassGisParameterRegion -from egoio.db_tables import model_draft, grid + if not 'READTHEDOCS' in os.environ: import pyproj as proj @@ -39,6 +26,20 @@ from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.automap import automap_base from geoalchemy2 import * + from egoio.tools import db + from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, + curtailment, gen_dist, storage_distribution, + plot_voltage, plot_residual_load + ) + from tools.results import (create_etrago_results) + from tools.storages import (total_storage_charges, etrago_storages) + from tools.economics import (etrago_operating_costs, etrago_grid_investment, + edisgo_grid_investment, investment_costs, + get_generator_investment) + from tools.utilities import get_scenario_setting, get_time_steps + from etrago.appl import etrago + from egoio.db_tables.model_draft import RenpassGisParameterRegion + from egoio.db_tables import model_draft, grid class egoBasic(object): From 4c37add1ca773a4c209e5a3bb96ba32cb4697019 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:38:45 +0200 Subject: [PATCH 089/314] change structure for rtd --- ego/tools/io.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index b6b37c43..14d8bdf8 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -17,6 +17,10 @@ import numpy as np +from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, + curtailment, gen_dist, storage_distribution, + plot_voltage, plot_residual_load) + if not 'READTHEDOCS' in os.environ: import pyproj as proj import geopandas as gpd @@ -26,11 +30,8 @@ from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.automap import automap_base from geoalchemy2 import * + from egoio.tools import db - from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, - curtailment, gen_dist, storage_distribution, - plot_voltage, plot_residual_load - ) from tools.results import (create_etrago_results) from tools.storages import (total_storage_charges, etrago_storages) from tools.economics import (etrago_operating_costs, etrago_grid_investment, From 457b8c34e960631e6e8776aa97acfe2284043faa Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:44:07 +0200 Subject: [PATCH 090/314] change structure for rtd --- ego/tools/io.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ego/tools/io.py b/ego/tools/io.py index 14d8bdf8..fa86ae8d 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -20,6 +20,7 @@ from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, curtailment, gen_dist, storage_distribution, plot_voltage, plot_residual_load) +from etrago.appl import etrago if not 'READTHEDOCS' in os.environ: import pyproj as proj From 7c94594ae7294cfd2891397971eca433562f7dfb Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:48:16 +0200 Subject: [PATCH 091/314] update rtd --- ego/ego_main.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 6f57c2b4..8cb18643 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -16,15 +16,17 @@ import pandas as pd import os -import logging - -if not 'READTHEDOCS' in os.environ: - from tools.io import eGo - #from etrago.tools.io import results_to_oedb from tools.utilities import define_logging logger = define_logging(log_name='ego.log') +from tools.io import eGo + +# if not 'READTHEDOCS' in os.environ: +# from tools.io import eGo +#from etrago.tools.io import results_to_oedb + + if __name__ == '__main__': # import scenario settings **args of eTraGo From 33a466accdff6a57f7c6d4da9639ec9c4aa58191 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:50:35 +0200 Subject: [PATCH 092/314] update rtd --- ego/tools/economics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index e1f8b535..f055d223 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -58,8 +58,8 @@ def etrago_operating_costs(network): -------- - losses - - grid losses : amount and costs - - use calc_line_losses(network) from etrago pf_post_lopf + - grid losses : amount and costs + - use calc_line_losses(network) from etrago pf_post_lopf ToDo ---- From 499bad00d36c952ef3589340fa522c73db92dfb3 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:52:40 +0200 Subject: [PATCH 093/314] update rtd --- ego/tools/plots.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ego/tools/plots.py b/ego/tools/plots.py index 1e978d14..dc8609f9 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -107,9 +107,9 @@ def igeoplot(network, session, tiles=None, geoloc=None, args=None): Define center of map as (lon,lat) Returns -------- - - HTML Plot page + ------- + plot : html + HTML file this .js plot ToDo ---- From 64ecfa14f4bfb11ad831bf13cb6cb1f71dbc64e6 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:54:30 +0200 Subject: [PATCH 094/314] update rtd --- doc/api/ego.tools.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/ego.tools.rst b/doc/api/ego.tools.rst index d018e051..92ff212e 100644 --- a/doc/api/ego.tools.rst +++ b/doc/api/ego.tools.rst @@ -46,7 +46,7 @@ ego\.tools\.specs :show-inheritance: ego\.tools\.storages ------------------ +-------------------- .. automodule:: ego.tools.storages :members: From 0f9fb2700e8c58fbccfb89614993a1d71aedcd7a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 13:59:47 +0200 Subject: [PATCH 095/314] update import for rtd --- ego/ego_main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 8cb18643..6deb0a59 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -17,10 +17,10 @@ import pandas as pd import os -from tools.utilities import define_logging +from ego.tools.utilities import define_logging logger = define_logging(log_name='ego.log') -from tools.io import eGo +from ego.tools.io import eGo # if not 'READTHEDOCS' in os.environ: # from tools.io import eGo From 002078ae940b6f41b8fffa9dd1bccb0a5ed2ed59 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 14:03:45 +0200 Subject: [PATCH 096/314] update rtd --- ego/ego_main.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 6deb0a59..3837440f 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -34,8 +34,7 @@ ego = eGo(jsonpath='scenario_setting.json') - print(ego.etrago.storage_charges) - ego.etrago_network.plot() + """ # add country code to bus and geometry (shapely) From 23ca74aa5a6cf0a8bcde37bd6ef7998a1eaf30f2 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 14:09:00 +0200 Subject: [PATCH 097/314] update rtd --- ego/ego_main.py | 2 +- ego/tools/io.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 3837440f..fa354775 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -21,7 +21,7 @@ logger = define_logging(log_name='ego.log') from ego.tools.io import eGo - +import etrago.etrago as etrago # if not 'READTHEDOCS' in os.environ: # from tools.io import eGo #from etrago.tools.io import results_to_oedb diff --git a/ego/tools/io.py b/ego/tools/io.py index fa86ae8d..94ca290c 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -68,7 +68,7 @@ class egoBasic(object): """ def __init__(self, - jsonpath, * args, **kwargs): # eTraGo=None + jsonpath, * args, **kwargs): self.jsonpath = 'scenario_setting.json' self.json_file = get_scenario_setting(self.jsonpath) From 70d6d9d1fc69df2ffa5dedb7bbc7fb5a534ca7dc Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 14:14:25 +0200 Subject: [PATCH 098/314] update rtd --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index b0cd619a..162ac2cb 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -261,7 +261,7 @@ def __getattr__(cls, name): # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] +html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied From a28f3989d1fa6ee7b114ed274fb1b8c4e932df5b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 14:19:31 +0200 Subject: [PATCH 099/314] update rtd --- ego/tools/io.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 94ca290c..c0ce9169 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -153,12 +153,12 @@ def __init__(self, jsonpath, *args, **kwargs): pass # include eTraGo functions and methods - def etrago_line_loading(self, **kwargs): - """ - Integrate and use function from eTraGo. - For more information see: - """ - return plot_line_loading(network=self.etrago_network, **kwargs) + # def etrago_line_loading(self, **kwargs): + # """ + # Integrate and use function from eTraGo. + # For more information see: + # """ + # return plot_line_loading(network=self.etrago_network, **kwargs) # def etrago_stacked_gen(self, **kwargs): # """ From d4a318b0749ad54f29058b3ca1b9c98350050963 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 14:22:21 +0200 Subject: [PATCH 100/314] update rtd --- ego/tools/io.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index c0ce9169..a890beb3 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -17,11 +17,6 @@ import numpy as np -from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, - curtailment, gen_dist, storage_distribution, - plot_voltage, plot_residual_load) -from etrago.appl import etrago - if not 'READTHEDOCS' in os.environ: import pyproj as proj import geopandas as gpd @@ -42,6 +37,10 @@ from etrago.appl import etrago from egoio.db_tables.model_draft import RenpassGisParameterRegion from egoio.db_tables import model_draft, grid + from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, + curtailment, gen_dist, storage_distribution, + plot_voltage, plot_residual_load) + from etrago.appl import etrago class egoBasic(object): From d9255124d2f324bb93d8896859e4f2385a2861c8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 14:37:07 +0200 Subject: [PATCH 101/314] update rtd --- ego/ego_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index fa354775..3837440f 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -21,7 +21,7 @@ logger = define_logging(log_name='ego.log') from ego.tools.io import eGo -import etrago.etrago as etrago + # if not 'READTHEDOCS' in os.environ: # from tools.io import eGo #from etrago.tools.io import results_to_oedb From 0757d3b3130a771b694d7736f72e3c3d1169d85c Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 14:39:45 +0200 Subject: [PATCH 102/314] update rtd --- ego/tools/io.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index a890beb3..17d3bdb5 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -48,11 +48,13 @@ class egoBasic(object): `scenario_setting.json` file your definde eTraGo and eDisGo results container. + Parameters ---------- jsonpath : :obj:`json` Path to _scenario_setting.json_ file. + Results ------- eTraGo : :pandas:`pandas.Dataframe` of PyPSA @@ -147,17 +149,17 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago.generator = create_etrago_results(self.etrago_network, self.scn_name) # add functions direct - #self.etrago_network.etrago_line_loading = etrago_line_loading + # self.etrago_network.etrago_line_loading = etrago_line_loading pass # include eTraGo functions and methods - # def etrago_line_loading(self, **kwargs): - # """ - # Integrate and use function from eTraGo. - # For more information see: - # """ - # return plot_line_loading(network=self.etrago_network, **kwargs) + def etrago_line_loading(self, **kwargs): + """ + Integrate and use function from eTraGo. + For more information see: + """ + return plot_line_loading(network=self.etrago_network, **kwargs) # def etrago_stacked_gen(self, **kwargs): # """ From 690cdab5a3ba33990a92b86504f32dedafa5cf71 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 14:53:09 +0200 Subject: [PATCH 103/314] update rtd --- ego/tools/io.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 17d3bdb5..4af2488e 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -154,12 +154,12 @@ def __init__(self, jsonpath, *args, **kwargs): pass # include eTraGo functions and methods - def etrago_line_loading(self, **kwargs): + def etrago_line_loading(self, **kwargs): """ - Integrate and use function from eTraGo. - For more information see: - """ - return plot_line_loading(network=self.etrago_network, **kwargs) + Integrate and use function from eTraGo. + For more information see: + """ + return plot_line_loading(network=self.etrago_network, **kwargs) # def etrago_stacked_gen(self, **kwargs): # """ From 626796ff80ffdb4f6bf9e232324d1f825ef36cd0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 15:36:09 +0200 Subject: [PATCH 104/314] update file for rtd --- ego/tools/io.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 4af2488e..469cb783 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -153,13 +153,14 @@ def __init__(self, jsonpath, *args, **kwargs): pass - # include eTraGo functions and methods - def etrago_line_loading(self, **kwargs): - """ - Integrate and use function from eTraGo. - For more information see: - """ - return plot_line_loading(network=self.etrago_network, **kwargs) + if not 'READTHEDOCS' in os.environ: + # include eTraGo functions and methods + def etrago_line_loading(self, **kwargs): + """ + Integrate and use function from eTraGo. + For more information see: + """ + return plot_line_loading(network=self.etrago_network, **kwargs) # def etrago_stacked_gen(self, **kwargs): # """ From fcc2675abef2e5b738388048228fc22b1d462e40 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 16:02:51 +0200 Subject: [PATCH 105/314] update file --- ego/ego_main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ego/ego_main.py b/ego/ego_main.py index 3837440f..3872f902 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -33,6 +33,7 @@ logger.info('Start calculation') ego = eGo(jsonpath='scenario_setting.json') + ego.etrago_line_loading() """ From ca54ac3d3e36ca58839510445d842b869b5cc599 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 5 Jul 2018 16:23:30 +0200 Subject: [PATCH 106/314] implement 'READTHEDOCS' in os.environ: --- ego/tools/io.py | 82 ++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 469cb783..00b3bf6a 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -162,47 +162,47 @@ def etrago_line_loading(self, **kwargs): """ return plot_line_loading(network=self.etrago_network, **kwargs) - # def etrago_stacked_gen(self, **kwargs): - # """ - # Integrate function from eTraGo. - # For more information see: - # """ - # return plot_stacked_gen(network=self.etrago_network, **kwargs) - - # def etrago_curtailment(self, **kwargs): - # """ - # Integrate function from eTraGo. - # For more information see: - # """ - # return curtailment(network=self.etrago_network, **kwargs) - - # def etrago_gen_dist(self, **kwargs): - # """ - # Integrate function from eTraGo. - # For more information see: - # """ - # return gen_dist(network=self.etrago_network, **kwargs) - - # def etrago_storage_distribution(self, **kwargs): - # """ - # Integrate function from eTraGo. - # For more information see: - # """ - # return storage_distribution(network=self.etrago_network, **kwargs) - - # def etrago_voltage(self, **kwargs): - # """ - # Integrate function from eTraGo. - # For more information see: - # """ - # return plot_voltage(network=self.etrago_network, **kwargs) - - # def etrago_residual_load(self, **kwargs): - # """ - # Integrate function from eTraGo. - # For more information see: - # """ - # return plot_residual_load(network=self.etrago_network, **kwargs) + def etrago_stacked_gen(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return plot_stacked_gen(network=self.etrago_network, **kwargs) + + def etrago_curtailment(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return curtailment(network=self.etrago_network, **kwargs) + + def etrago_gen_dist(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return gen_dist(network=self.etrago_network, **kwargs) + + def etrago_storage_distribution(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return storage_distribution(network=self.etrago_network, **kwargs) + + def etrago_voltage(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return plot_voltage(network=self.etrago_network, **kwargs) + + def etrago_residual_load(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return plot_residual_load(network=self.etrago_network, **kwargs) # add other methods from eTraGo here From a541a16e018d37a70648f1d7a8b041c9cf5fecac Mon Sep 17 00:00:00 2001 From: maltesc Date: Thu, 5 Jul 2018 16:55:14 +0200 Subject: [PATCH 107/314] minor changes --- ego/ego_main.py | 4 +- ego/scenario_setting.json | 7 +- ego/tools/io.py | 4 +- ego/tools/specs.py | 689 +++++++++++++++++++------------------- 4 files changed, 351 insertions(+), 353 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index cec48029..8de3ec22 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -32,8 +32,8 @@ ego = eGo(jsonpath='scenario_setting.json') - print(ego.etrago.storage_charges) - ego.etrago_network.plot() +# print(ego.etrago.storage_charges) +# ego.etrago_network.plot() """ # add country code to bus and geometry (shapely) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index ad2c2fec..bf77a204 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -24,7 +24,7 @@ "results": false, "export": false, "extendable": "['storages']", - "generator_noise": false, + "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, "network_clustering_kmeans": 20, @@ -35,12 +35,11 @@ "skip_snapshots": false, "line_grouping": false, "branch_capacity_factor": 1, - "load_shedding": false, + "load_shedding": true, "comments": null }, "eDisGo": { - "direct_specs": false, "specs": true, - "comments": "make a comment, SH SQ" + "comments": "make a comment" } } diff --git a/ego/tools/io.py b/ego/tools/io.py index 0be01553..e6240d61 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -64,7 +64,7 @@ class egoBasic(object): """ def __init__(self, - jsonpath, * args, **kwargs): # eTraGo=None + jsonpath, *args, **kwargs): self.jsonpath = 'scenario_setting.json' self.json_file = get_scenario_setting(self.jsonpath) @@ -90,7 +90,7 @@ def __init__(self, if self.json_file['global']['eDisGo'] is True: logger.info('Create eDisGo network') - self.edisgo_network = None # add eDisGo initialisation here + self.edisgo_networks = None pass diff --git a/ego/tools/specs.py b/ego/tools/specs.py index 6fc10300..de57347b 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -14,351 +14,350 @@ # Functions - -def get_etragospecs_from_db(session, - bus_id, - result_id): - """ - Reads eTraGo Results from Database and returns an Object of the Interface class ETraGoSpecs - - Parameters - ---------- - session : :class:`~.` #Todo: Add class etc.... - Oemof session object (Database Interface) - bus_id : int - ID of the corresponding HV bus - result_id : int - ID of the corresponding database result - - - Returns - ------- - etragospecs : :class:~.` - eDisGo ETraGoSpecs Object - - """ - print("\nSpecs from DB") - specs_meta_data = {} - performance = {} - - specs_meta_data.update({'TG Bus ID': bus_id}) - specs_meta_data.update({'Result ID': result_id}) - - # Mapping - ormclass_result_meta = model_draft.__getattribute__('EgoGridPfHvResultMeta') - # Instead of using the automapper, this is the explicit alternative (from egoei.db_tables). - ormclass_result_bus = model_draft.__getattribute__('EgoGridPfHvResultBus') - # ormclass_result_bus = model_draft.EgoGridPfHvResultBus # This is equivalent - #ormclass_result_bus_t = model_draft.__getattribute__('EgoGridPfHvResultBusT') - ormclass_result_gen = model_draft.__getattribute__( - 'EgoGridPfHvResultGenerator') - ormclass_result_gen_t = model_draft.__getattribute__( - 'EgoGridPfHvResultGeneratorT') - #ormclass_result_gen_single = model_draft.__getattribute__('EgoSupplyPfGeneratorSingle') - #ormclass_result_load = model_draft.__getattribute__('EgoGridPfHvResultLoad') - #ormclass_result_load_t = model_draft.__getattribute__('EgoGridPfHvResultLoadT') - ormclass_result_stor = model_draft.__getattribute__( - 'EgoGridPfHvResultStorage') - ormclass_result_stor_t = model_draft.__getattribute__( - 'EgoGridPfHvResultStorageT') - ormclass_source = model_draft.__getattribute__('EgoGridPfHvSource') - ormclass_aggr_w = model_draft.__getattribute__( - 'ego_supply_aggr_weather_mview') - - # Meta Queries - # Check - - if session.query(ormclass_result_bus).filter( - ormclass_result_bus.bus_id == bus_id, - ormclass_result_bus.result_id == result_id - ).count() == 0: - logger.warning('Bus not found') - - # Snapshot Range - - snap_idx = session.query( - ormclass_result_meta.snapshots - ).filter( - ormclass_result_meta.result_id == result_id - ).scalar( - ) - - scn_name = session.query( - ormclass_result_meta.scn_name - ).filter( - ormclass_result_meta.result_id == result_id - ).scalar( - ) - if scn_name == 'SH Status Quo': - scn_name = 'Status Quo' - - specs_meta_data.update({'scn_name': scn_name}) - - # Generators - - try: - t0 = time.perf_counter() - weather_dpdnt = ['wind', 'solar'] - # Conventionals - t1 = time.perf_counter() - performance.update({'Generator Data Processing': t1-t0}) - - query = session.query( - # This ID is an aggregate ID (single generators aggregated) - ormclass_result_gen.generator_id, - ormclass_result_gen.p_nom, - ormclass_source.name - ).join( - ormclass_source, - ormclass_source.source_id == ormclass_result_gen.source - ).filter( - ormclass_result_gen.bus == bus_id, - ormclass_result_gen.result_id == result_id, - ormclass_source.name.notin_(weather_dpdnt)) - - conv_df = pd.DataFrame(query.all(), - columns=[column['name'] for - column in - query.column_descriptions]) - - conv_cap = conv_df[['p_nom', 'name']].groupby('name').sum().T - - query = session.query( - ormclass_result_gen_t.generator_id, - ormclass_result_gen_t.p - ).filter( - ormclass_result_gen_t.generator_id.in_(conv_df['generator_id']), - ormclass_result_gen_t.result_id == result_id - ) - - conv_t_df = pd.DataFrame(query.all(), - columns=[column['name'] for column in query.column_descriptions]) - - conv_t_df = pd.merge(conv_df, - conv_t_df, - on='generator_id')[[ - 'name', - 'p']] - - conv_dsptch_norm = pd.DataFrame(0.0, - index=snap_idx, - columns=list(set(conv_df['name']))) - - for index, row in conv_t_df.iterrows(): - source = row['name'] - gen_series_norm = pd.Series( - # Every generator normalized by installed capacity. - data=(row['p'] / conv_cap[source]['p_nom']), - index=snap_idx) - conv_dsptch_norm[source] = conv_dsptch_norm[source] + \ - gen_series_norm - - # Renewables - t2 = time.perf_counter() - performance.update({'Conventional Dispatch': t2-t1}) - # Capacities - - query = session.query( - ormclass_result_gen.generator_id, - ormclass_result_gen.p_nom, - ormclass_result_gen.p_nom_opt, - ormclass_source.name, - ormclass_aggr_w.c.w_id - ).join( - ormclass_source, - ormclass_source.source_id == ormclass_result_gen.source - ).join( - ormclass_aggr_w, - ormclass_aggr_w.c.aggr_id == ormclass_result_gen.generator_id - - ).filter( - ormclass_result_gen.bus == bus_id, - ormclass_result_gen.result_id == result_id, - ormclass_source.name.in_(weather_dpdnt), - ormclass_aggr_w.c.scn_name == scn_name) - - ren_df = pd.DataFrame(query.all(), - columns=[column['name'] for - column in - query.column_descriptions]) - - aggr_gens = ren_df.groupby([ - 'name', - 'w_id' - ]).agg({'p_nom': 'sum'}).reset_index() - - aggr_gens.rename(columns={'p_nom': 'p_nom_aggr'}, inplace=True) - - aggr_gens['ren_id'] = aggr_gens.index - - ### Dispatch and Curteilment - - query = session.query( - # This is an aggregated generator ID (see ego_dp_powerflow_assignment_generator for info) - ormclass_result_gen_t.generator_id, - ormclass_result_gen_t.p, - # The maximum output for each snapshot per unit of p_nom for the OPF (e.g. for variable renewable generators this can change due to weather conditions; for conventional generators it represents a maximum dispatch) - ormclass_result_gen_t.p_max_pu - ).filter( - ormclass_result_gen_t.generator_id.in_(ren_df['generator_id']), - ormclass_result_gen_t.result_id == result_id - ) - - ren_t_df = pd.DataFrame(query.all(), - columns=[column['name'] for - column in - query.column_descriptions]) - ren_t_df = pd.merge(ren_t_df, ren_df, on='generator_id')[[ - 'generator_id', - 'w_id', - 'name', - 'p', - 'p_max_pu']] - - dispatch = pd.DataFrame(0.0, - index=snap_idx, - columns=aggr_gens['ren_id']) - curtailment = pd.DataFrame(0.0, - index=snap_idx, - columns=aggr_gens['ren_id']) - - for index, row in ren_t_df.iterrows(): - gen_id = row['generator_id'] - name = row['name'] - w_id = row['w_id'] - ren_id = int(aggr_gens[ - (aggr_gens['name'] == name) & - (aggr_gens['w_id'] == w_id)]['ren_id']) - - p_nom_aggr = float( - aggr_gens[aggr_gens['ren_id'] == ren_id]['p_nom_aggr']) - p_nom = float(ren_df[ren_df['generator_id'] == gen_id]['p_nom']) - - p_series = pd.Series(data=row['p'], index=snap_idx) - p_norm_tot_series = p_series / p_nom_aggr - - p_max_pu_series = pd.Series(data=row['p_max_pu'], index=snap_idx) - p_max_norm_tot_series = p_max_pu_series * p_nom / p_nom_aggr - - p_curt_norm_tot_series = p_max_norm_tot_series - p_norm_tot_series - - dispatch[ren_id] = dispatch[ren_id] + p_norm_tot_series - curtailment[ren_id] = curtailment[ren_id] + p_curt_norm_tot_series - - except: - logger.exception("Generators could not be queried for \ - Specs with Metadata: \n %s" % specs_meta_data) - - # Load - # Load are not part of the Specs anymore - - # Storage - t3 = time.perf_counter() - performance.update({'Renewable Dispatch and Curt.': t3-t2}) - try: - # Capactiy - query = session.query( - ormclass_result_stor.storage_id, - ormclass_result_stor.p_nom_opt, - ormclass_result_stor.p_nom, - ormclass_result_stor.max_hours, - ormclass_source.name - ).join( - ormclass_source, - ormclass_source.source_id == ormclass_result_stor.source - ).filter( - ormclass_result_stor.bus == bus_id, - ormclass_result_stor.result_id == result_id, - ormclass_source.name == 'extendable_storage') - - stor_df = pd.DataFrame(query.all(), - columns=[column['name'] for - column in - query.column_descriptions]) - - stor_df['capacity_MWh'] = stor_df['p_nom_opt'] * stor_df['max_hours'] - - count_bat = 0 - for index, row in stor_df.iterrows(): - if row['max_hours'] >= 20.0: - stor_df.at[index, 'name'] = 'ext_long_term' - else: - # ToDo: find a more generic solution - stor_df.at[index, 'name'] = 'battery' - count_bat += 1 - - # Project Specific Battery Capacity - battery_capacity = 0.0 # MWh - for index, row in stor_df.iterrows(): - if row['name'] == 'battery': - battery_capacity = battery_capacity + row['capacity_MWh'] - - # Dispatch - query = session.query( - ormclass_result_stor_t.storage_id, - ormclass_result_stor_t.p, - ormclass_result_stor_t.state_of_charge - ).filter( - ormclass_result_stor_t.storage_id.in_( - stor_df['storage_id']), - ormclass_result_stor_t.result_id == result_id - ) - stor_t_df = pd.DataFrame(query.all(), - columns=[column['name'] for - column in - query.column_descriptions]) - - stor_t_df = pd.merge(stor_t_df, stor_df, on='storage_id')[[ - 'storage_id', - 'name', - 'p', - 'state_of_charge']] - - # Project Specific Battery Active Power - battery_active_power = pd.Series(0.0, index=snap_idx) - for index, row in stor_t_df.iterrows(): - name = row['name'] - if name == 'battery': - stor_series = pd.Series( - data=row['p'], # in MW - index=snap_idx) - stor_series_kW = [x * 1000 for x in stor_series] # in kW - battery_active_power = battery_active_power + stor_series_kW - - except: - logger.exception("Storage could not be queried for \ - Specs with Metadata: \n %s" % specs_meta_data) - - # Return Specs - t4 = time.perf_counter() - performance.update({'Storage Data Processing and Dispatch': t4-t3}) - - specs = ETraGoSpecs(battery_capacity=battery_capacity, - battery_active_power=battery_active_power, - - conv_dispatch=conv_dsptch_norm, - - renewables=aggr_gens, - ren_dispatch=dispatch, - ren_curtailment=curtailment) - - # logger.info(specs_meta_data) - t5 = time.perf_counter() - performance.update({'Overall time': t5-t0}) - -# print("\n Conventional Dispatch (Normalized): \n", -# conv_dsptch_norm, -# "\n\n Renewable Generators: \n", -# aggr_gens, -# "\n\n Renewable Dispatch: \n", -# dispatch, -# "\n\n Renewable Curtailment: \n", -# curtailment, "\n\n") - - for keys, values in performance.items(): - print(keys, ": ", values) - - return specs +#def get_etragospecs_from_db(session, +# bus_id, +# result_id): +# """ +# Reads eTraGo Results from Database and returns an Object of the Interface class ETraGoSpecs +# +# Parameters +# ---------- +# session : :class:`~.` #Todo: Add class etc.... +# Oemof session object (Database Interface) +# bus_id : int +# ID of the corresponding HV bus +# result_id : int +# ID of the corresponding database result +# +# +# Returns +# ------- +# etragospecs : :class:~.` +# eDisGo ETraGoSpecs Object +# +# """ +# print("\nSpecs from DB") +# specs_meta_data = {} +# performance = {} +# +# specs_meta_data.update({'TG Bus ID': bus_id}) +# specs_meta_data.update({'Result ID': result_id}) +# +# # Mapping +# ormclass_result_meta = model_draft.__getattribute__('EgoGridPfHvResultMeta') +# # Instead of using the automapper, this is the explicit alternative (from egoei.db_tables). +# ormclass_result_bus = model_draft.__getattribute__('EgoGridPfHvResultBus') +# # ormclass_result_bus = model_draft.EgoGridPfHvResultBus # This is equivalent +# #ormclass_result_bus_t = model_draft.__getattribute__('EgoGridPfHvResultBusT') +# ormclass_result_gen = model_draft.__getattribute__( +# 'EgoGridPfHvResultGenerator') +# ormclass_result_gen_t = model_draft.__getattribute__( +# 'EgoGridPfHvResultGeneratorT') +# #ormclass_result_gen_single = model_draft.__getattribute__('EgoSupplyPfGeneratorSingle') +# #ormclass_result_load = model_draft.__getattribute__('EgoGridPfHvResultLoad') +# #ormclass_result_load_t = model_draft.__getattribute__('EgoGridPfHvResultLoadT') +# ormclass_result_stor = model_draft.__getattribute__( +# 'EgoGridPfHvResultStorage') +# ormclass_result_stor_t = model_draft.__getattribute__( +# 'EgoGridPfHvResultStorageT') +# ormclass_source = model_draft.__getattribute__('EgoGridPfHvSource') +# ormclass_aggr_w = model_draft.__getattribute__( +# 'ego_supply_aggr_weather_mview') +# +# # Meta Queries +# # Check +# +# if session.query(ormclass_result_bus).filter( +# ormclass_result_bus.bus_id == bus_id, +# ormclass_result_bus.result_id == result_id +# ).count() == 0: +# logger.warning('Bus not found') +# +# # Snapshot Range +# +# snap_idx = session.query( +# ormclass_result_meta.snapshots +# ).filter( +# ormclass_result_meta.result_id == result_id +# ).scalar( +# ) +# +# scn_name = session.query( +# ormclass_result_meta.scn_name +# ).filter( +# ormclass_result_meta.result_id == result_id +# ).scalar( +# ) +# if scn_name == 'SH Status Quo': +# scn_name = 'Status Quo' +# +# specs_meta_data.update({'scn_name': scn_name}) +# +# # Generators +# +# try: +# t0 = time.perf_counter() +# weather_dpdnt = ['wind', 'solar'] +# # Conventionals +# t1 = time.perf_counter() +# performance.update({'Generator Data Processing': t1-t0}) +# +# query = session.query( +# # This ID is an aggregate ID (single generators aggregated) +# ormclass_result_gen.generator_id, +# ormclass_result_gen.p_nom, +# ormclass_source.name +# ).join( +# ormclass_source, +# ormclass_source.source_id == ormclass_result_gen.source +# ).filter( +# ormclass_result_gen.bus == bus_id, +# ormclass_result_gen.result_id == result_id, +# ormclass_source.name.notin_(weather_dpdnt)) +# +# conv_df = pd.DataFrame(query.all(), +# columns=[column['name'] for +# column in +# query.column_descriptions]) +# +# conv_cap = conv_df[['p_nom', 'name']].groupby('name').sum().T +# +# query = session.query( +# ormclass_result_gen_t.generator_id, +# ormclass_result_gen_t.p +# ).filter( +# ormclass_result_gen_t.generator_id.in_(conv_df['generator_id']), +# ormclass_result_gen_t.result_id == result_id +# ) +# +# conv_t_df = pd.DataFrame(query.all(), +# columns=[column['name'] for column in query.column_descriptions]) +# +# conv_t_df = pd.merge(conv_df, +# conv_t_df, +# on='generator_id')[[ +# 'name', +# 'p']] +# +# conv_dsptch_norm = pd.DataFrame(0.0, +# index=snap_idx, +# columns=list(set(conv_df['name']))) +# +# for index, row in conv_t_df.iterrows(): +# source = row['name'] +# gen_series_norm = pd.Series( +# # Every generator normalized by installed capacity. +# data=(row['p'] / conv_cap[source]['p_nom']), +# index=snap_idx) +# conv_dsptch_norm[source] = conv_dsptch_norm[source] + \ +# gen_series_norm +# +# # Renewables +# t2 = time.perf_counter() +# performance.update({'Conventional Dispatch': t2-t1}) +# # Capacities +# +# query = session.query( +# ormclass_result_gen.generator_id, +# ormclass_result_gen.p_nom, +# ormclass_result_gen.p_nom_opt, +# ormclass_source.name, +# ormclass_aggr_w.c.w_id +# ).join( +# ormclass_source, +# ormclass_source.source_id == ormclass_result_gen.source +# ).join( +# ormclass_aggr_w, +# ormclass_aggr_w.c.aggr_id == ormclass_result_gen.generator_id +# +# ).filter( +# ormclass_result_gen.bus == bus_id, +# ormclass_result_gen.result_id == result_id, +# ormclass_source.name.in_(weather_dpdnt), +# ormclass_aggr_w.c.scn_name == scn_name) +# +# ren_df = pd.DataFrame(query.all(), +# columns=[column['name'] for +# column in +# query.column_descriptions]) +# +# aggr_gens = ren_df.groupby([ +# 'name', +# 'w_id' +# ]).agg({'p_nom': 'sum'}).reset_index() +# +# aggr_gens.rename(columns={'p_nom': 'p_nom_aggr'}, inplace=True) +# +# aggr_gens['ren_id'] = aggr_gens.index +# +# ### Dispatch and Curteilment +# +# query = session.query( +# # This is an aggregated generator ID (see ego_dp_powerflow_assignment_generator for info) +# ormclass_result_gen_t.generator_id, +# ormclass_result_gen_t.p, +# # The maximum output for each snapshot per unit of p_nom for the OPF (e.g. for variable renewable generators this can change due to weather conditions; for conventional generators it represents a maximum dispatch) +# ormclass_result_gen_t.p_max_pu +# ).filter( +# ormclass_result_gen_t.generator_id.in_(ren_df['generator_id']), +# ormclass_result_gen_t.result_id == result_id +# ) +# +# ren_t_df = pd.DataFrame(query.all(), +# columns=[column['name'] for +# column in +# query.column_descriptions]) +# ren_t_df = pd.merge(ren_t_df, ren_df, on='generator_id')[[ +# 'generator_id', +# 'w_id', +# 'name', +# 'p', +# 'p_max_pu']] +# +# dispatch = pd.DataFrame(0.0, +# index=snap_idx, +# columns=aggr_gens['ren_id']) +# curtailment = pd.DataFrame(0.0, +# index=snap_idx, +# columns=aggr_gens['ren_id']) +# +# for index, row in ren_t_df.iterrows(): +# gen_id = row['generator_id'] +# name = row['name'] +# w_id = row['w_id'] +# ren_id = int(aggr_gens[ +# (aggr_gens['name'] == name) & +# (aggr_gens['w_id'] == w_id)]['ren_id']) +# +# p_nom_aggr = float( +# aggr_gens[aggr_gens['ren_id'] == ren_id]['p_nom_aggr']) +# p_nom = float(ren_df[ren_df['generator_id'] == gen_id]['p_nom']) +# +# p_series = pd.Series(data=row['p'], index=snap_idx) +# p_norm_tot_series = p_series / p_nom_aggr +# +# p_max_pu_series = pd.Series(data=row['p_max_pu'], index=snap_idx) +# p_max_norm_tot_series = p_max_pu_series * p_nom / p_nom_aggr +# +# p_curt_norm_tot_series = p_max_norm_tot_series - p_norm_tot_series +# +# dispatch[ren_id] = dispatch[ren_id] + p_norm_tot_series +# curtailment[ren_id] = curtailment[ren_id] + p_curt_norm_tot_series +# +# except: +# logger.exception("Generators could not be queried for \ +# Specs with Metadata: \n %s" % specs_meta_data) +# +# # Load +# # Load are not part of the Specs anymore +# +# # Storage +# t3 = time.perf_counter() +# performance.update({'Renewable Dispatch and Curt.': t3-t2}) +# try: +# # Capactiy +# query = session.query( +# ormclass_result_stor.storage_id, +# ormclass_result_stor.p_nom_opt, +# ormclass_result_stor.p_nom, +# ormclass_result_stor.max_hours, +# ormclass_source.name +# ).join( +# ormclass_source, +# ormclass_source.source_id == ormclass_result_stor.source +# ).filter( +# ormclass_result_stor.bus == bus_id, +# ormclass_result_stor.result_id == result_id, +# ormclass_source.name == 'extendable_storage') +# +# stor_df = pd.DataFrame(query.all(), +# columns=[column['name'] for +# column in +# query.column_descriptions]) +# +# stor_df['capacity_MWh'] = stor_df['p_nom_opt'] * stor_df['max_hours'] +# +# count_bat = 0 +# for index, row in stor_df.iterrows(): +# if row['max_hours'] >= 20.0: +# stor_df.at[index, 'name'] = 'ext_long_term' +# else: +# # ToDo: find a more generic solution +# stor_df.at[index, 'name'] = 'battery' +# count_bat += 1 +# +# # Project Specific Battery Capacity +# battery_capacity = 0.0 # MWh +# for index, row in stor_df.iterrows(): +# if row['name'] == 'battery': +# battery_capacity = battery_capacity + row['capacity_MWh'] +# +# # Dispatch +# query = session.query( +# ormclass_result_stor_t.storage_id, +# ormclass_result_stor_t.p, +# ormclass_result_stor_t.state_of_charge +# ).filter( +# ormclass_result_stor_t.storage_id.in_( +# stor_df['storage_id']), +# ormclass_result_stor_t.result_id == result_id +# ) +# stor_t_df = pd.DataFrame(query.all(), +# columns=[column['name'] for +# column in +# query.column_descriptions]) +# +# stor_t_df = pd.merge(stor_t_df, stor_df, on='storage_id')[[ +# 'storage_id', +# 'name', +# 'p', +# 'state_of_charge']] +# +# # Project Specific Battery Active Power +# battery_active_power = pd.Series(0.0, index=snap_idx) +# for index, row in stor_t_df.iterrows(): +# name = row['name'] +# if name == 'battery': +# stor_series = pd.Series( +# data=row['p'], # in MW +# index=snap_idx) +# stor_series_kW = [x * 1000 for x in stor_series] # in kW +# battery_active_power = battery_active_power + stor_series_kW +# +# except: +# logger.exception("Storage could not be queried for \ +# Specs with Metadata: \n %s" % specs_meta_data) +# +# # Return Specs +# t4 = time.perf_counter() +# performance.update({'Storage Data Processing and Dispatch': t4-t3}) +# +# specs = ETraGoSpecs(battery_capacity=battery_capacity, +# battery_active_power=battery_active_power, +# +# conv_dispatch=conv_dsptch_norm, +# +# renewables=aggr_gens, +# ren_dispatch=dispatch, +# ren_curtailment=curtailment) +# +# # logger.info(specs_meta_data) +# t5 = time.perf_counter() +# performance.update({'Overall time': t5-t0}) +# +## print("\n Conventional Dispatch (Normalized): \n", +## conv_dsptch_norm, +## "\n\n Renewable Generators: \n", +## aggr_gens, +## "\n\n Renewable Dispatch: \n", +## dispatch, +## "\n\n Renewable Curtailment: \n", +## curtailment, "\n\n") +# +# for keys, values in performance.items(): +# print(keys, ": ", values) +# +# return specs def get_etragospecs_direct(session, From 039c2864a272b7df267d3bb451319ce05de64219 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:00:43 +0200 Subject: [PATCH 108/314] change version of eDisGo --- setup.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 57d29ac6..2a74e4e1 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ def read(fname): package_dir={'ego': 'ego'}, include_package_data=True, install_requires=['egoio==0.4.1', - 'eDisGo==0.0.2', + 'eDisGo==0.0.3', 'eTraGo==0.6', 'pandas==0.20.3', 'pypsa==0.11.0fork', @@ -37,6 +37,7 @@ def read(fname): 'matplotlib>= 1.5.3, <=1.5.3', 'Rtree==0.8.3', 'plotly==2.2.3' + 'oedialect' ], dependency_links=[('git+https://git@github.com/openego/PyPSA.git' '@dev#egg=pypsa-0.11.0fork') @@ -47,7 +48,9 @@ def read(fname): 'sphinx_rtd_theme', 'sphinxcontrib-httpdomain']}, package_data={ - 'ego': [os.path.join('tools/', '*.csv')], - 'ego.data': ['/*.csv'] + 'ego': [os.path.join('tools', '*.csv')], + 'ego': [os.path.join('tools', '*.json')], + 'ego': [os.path.join('', '*.json')] + 'ego.data': ['*.csv'] }, ) From f20e0429fa5d7ece1b9a20e75ca0f0655b5b16c3 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:04:55 +0200 Subject: [PATCH 109/314] update versions --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 2a74e4e1..47d4c9f3 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ def read(fname): setup(name='eGo', - version='0.2', + version='0.2dev', author='wolfbunke, maltesc', author_email='', description=("A python package for distribution and transmission" @@ -36,7 +36,7 @@ def read(fname): 'geopandas==0.3.0', 'matplotlib>= 1.5.3, <=1.5.3', 'Rtree==0.8.3', - 'plotly==2.2.3' + 'plotly==2.2.3', 'oedialect' ], dependency_links=[('git+https://git@github.com/openego/PyPSA.git' @@ -50,7 +50,7 @@ def read(fname): package_data={ 'ego': [os.path.join('tools', '*.csv')], 'ego': [os.path.join('tools', '*.json')], - 'ego': [os.path.join('', '*.json')] + 'ego': [os.path.join('', '*.json')], 'ego.data': ['*.csv'] }, ) From b6a1370b1f267575cab5b9d32f930d99f1132d3a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:25:26 +0200 Subject: [PATCH 110/314] update release notes --- doc/whatsnew/v0-2-0.rst | 45 ++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index 58e4ddb2..f303c293 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -1,8 +1,18 @@ -Release v0.2.0 (July 6, 2018) -+++++++++++++++++++++++++++++ +Release v0.2.0 (July 13, 2018) +++++++++++++++++++++++++++++++ -The second release of eGo ... -and is still under construction and not ready for a normal use. +The second release of the eGo application. + +New features have been included in this release. Major changes being the new +class structure and seperation of methods into the given file structure. +Moreover the use of the Dataprocessing version 'v0.4.1' and 'v0.4.2' is +integrate. For eGo and the integration and interaction the app will depend on a +data version >= 'v0.4.1' in order to ensure the correct data handling. +Furthermore the inclusion of new methods and classes for eDisGo, storages etc. +is done. + +Please note, that this release is still under construction and not ready +for a normal use. @@ -10,20 +20,23 @@ and is still under construction and not ready for a normal use. Added features -------------- -* clean and restructured eGo classes and functions -* add eTraGo features zo eGo -* add eDisGo ... -* updated to eTraGo 0.6, eDisGo 0.2 version -* implemented pep8 style -* implemented logging for the hole model -* moved class eGo from results.py to io.py -* Using the Restfull-API for the OpenEnergy Database connection, buy using - ego.io v0.4.2. A registration is needed and can be done on +* Cleaned and restructured eGo classes and functions +** Moved classes of eGo from results.py to io.py + +* Updated eTraGo 0.6 and integrated new functions and features to eGo +* Updated eDisGo 0.0.3 version which includes the features of a parallelization + for custom function and other important API changes. +* Implemented pep8 style to eGo Code +* Implemented logging function for the hole model +* Using the Restfull-API for the OpenEnergy Database connection, buy using + ego.io v0.4.2. A registration is needed and can be done on `openenergy-platform.org/login `_ -* introduce new file storages.py -* remove functionalities from main to the eGo class +* Introduce new file storages.py and xxx edisgo.py +* Remove functionalities from main to the eGo class * ... Notes ----- -* AS an external user you need to +* AS an external user you need to have and account on the + `openenergy-platform.org/login `_ +* ... From 0f69a783b5df73f98ee1a185b544b1273c6b2246 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:25:45 +0200 Subject: [PATCH 111/314] update release notes --- doc/whatsnew/v0-2-0.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index f303c293..472d97d8 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -14,9 +14,6 @@ is done. Please note, that this release is still under construction and not ready for a normal use. - - - Added features -------------- From 26f1a6398565fde6427f4492315491f671bcc97a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:27:42 +0200 Subject: [PATCH 112/314] pep8 --- doc/whatsnew/v0-0-1.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/doc/whatsnew/v0-0-1.rst b/doc/whatsnew/v0-0-1.rst index 5e7f028e..629f6914 100644 --- a/doc/whatsnew/v0-0-1.rst +++ b/doc/whatsnew/v0-0-1.rst @@ -1,17 +1,15 @@ Release v0.0.1 (February 02, 2018) ++++++++++++++++++++++++++++++++++ -As this is the first release of eGo. The tool eGo use the Python3 Packages eTraGo -(Optimization of flexibility options for transmission grids based on PyPSA) -and eDisGo (Optimization of flexibility options and grid expansion for -distribution grids based on PyPSA) for an electrical power calculation from extra high -voltage to selected low voltage level. - - +As this is the first release of eGo. The tool eGo use the Python3 Packages +eTraGo (Optimization of flexibility options for transmission grids based on +PyPSA) and eDisGo (Optimization of flexibility options and grid expansion for +distribution grids based on PyPSA) for an electrical power calculation from +extra high voltage to selected low voltage level. Added features -------------- * Interface between eTraGo and eDisGo * Plots with folium -* first Result structure +* first Result structure From 72024de96859d20c800d7336bfe6680b1ca46a5c Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:30:42 +0200 Subject: [PATCH 113/314] update release notes --- doc/whatsnew/v0-2-0.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index 472d97d8..2b4d0a9e 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -4,7 +4,7 @@ Release v0.2.0 (July 13, 2018) The second release of the eGo application. New features have been included in this release. Major changes being the new -class structure and seperation of methods into the given file structure. +class structure and separation of methods into the given file structure. Moreover the use of the Dataprocessing version 'v0.4.1' and 'v0.4.2' is integrate. For eGo and the integration and interaction the app will depend on a data version >= 'v0.4.1' in order to ensure the correct data handling. @@ -34,6 +34,6 @@ Added features Notes ----- -* AS an external user you need to have and account on the +* As an external user you need to have and account on the `openenergy-platform.org/login `_ * ... From ff70c71703a5fabb2dc3cba3f53b5ae08657057f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:31:58 +0200 Subject: [PATCH 114/314] change maxdepth for testing rtd --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 9a2cb99c..33168efc 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -12,7 +12,7 @@ Welcome to eGo documentation! .. toctree:: - :maxdepth: 7 + :maxdepth: 3 welcome getting_started From 61324a2b01d9107bb745263758e846b61a6d730f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:40:15 +0200 Subject: [PATCH 115/314] add background --- doc/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/index.rst b/doc/index.rst index 33168efc..6c150f01 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -17,6 +17,7 @@ Welcome to eGo documentation! welcome getting_started usage_details + theoretical_background developer whatsnew api From 5e011392602f97da9f902ee3902728f3a09427da Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:40:34 +0200 Subject: [PATCH 116/314] add background --- doc/theoretical_background.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 doc/theoretical_background.rst diff --git a/doc/theoretical_background.rst b/doc/theoretical_background.rst new file mode 100644 index 00000000..12ed49ee --- /dev/null +++ b/doc/theoretical_background.rst @@ -0,0 +1,20 @@ +====================== +Theoretical background +====================== + + + +Models overview +================ + + +.. figure:: images/open_ego_models_overview.png + :align: center + :scale: 99% + + + + + +References +========== From c67efca4a5528777fbb71ed5be27c53a019cb019 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:40:55 +0200 Subject: [PATCH 117/314] add model overview --- doc/images/open_ego_models_overview.png | Bin 0 -> 135910 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/images/open_ego_models_overview.png diff --git a/doc/images/open_ego_models_overview.png b/doc/images/open_ego_models_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..23663c617b12992961a6bca69509e1b171bbb305 GIT binary patch literal 135910 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 )!)x(iiyu7#K6CpSK_Xr`$Fmo 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�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

sT)+$G&Wf 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 literal 0 HcmV?d00001 From 3acb1faa11ffe0057805f17c8d7421181b7e428f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:51:44 +0200 Subject: [PATCH 118/314] update image import --- doc/theoretical_background.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/theoretical_background.rst b/doc/theoretical_background.rst index 12ed49ee..49ad525e 100644 --- a/doc/theoretical_background.rst +++ b/doc/theoretical_background.rst @@ -9,10 +9,11 @@ Models overview .. figure:: images/open_ego_models_overview.png + :width: 794px + :height: 1123px + :scale: 50% + :alt: Overview of Models and processes which are used by eGo :align: center - :scale: 99% - - From b764ed0070377723f3281b54b790da2df4a8cc11 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:55:01 +0200 Subject: [PATCH 119/314] update file --- doc/theoretical_background.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/theoretical_background.rst b/doc/theoretical_background.rst index 49ad525e..081e7ec7 100644 --- a/doc/theoretical_background.rst +++ b/doc/theoretical_background.rst @@ -11,7 +11,7 @@ Models overview .. figure:: images/open_ego_models_overview.png :width: 794px :height: 1123px - :scale: 50% + :scale: 100% :alt: Overview of Models and processes which are used by eGo :align: center From f9ba3bc7edae7a73db5e5c923679e289b1aec9ff Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 08:57:08 +0200 Subject: [PATCH 120/314] update file --- doc/theoretical_background.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/theoretical_background.rst b/doc/theoretical_background.rst index 081e7ec7..28fe89b9 100644 --- a/doc/theoretical_background.rst +++ b/doc/theoretical_background.rst @@ -9,9 +9,9 @@ Models overview .. figure:: images/open_ego_models_overview.png - :width: 794px - :height: 1123px - :scale: 100% + :width: 1123px + :height: 794px + :scale: 95% :alt: Overview of Models and processes which are used by eGo :align: center From 451c3c06c7d248719b623600ab142e2d7236b0a4 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 09:06:30 +0200 Subject: [PATCH 121/314] remove test file --- ego/test_ego.py | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 ego/test_ego.py diff --git a/ego/test_ego.py b/ego/test_ego.py deleted file mode 100644 index cefc6ffa..00000000 --- a/ego/test_ego.py +++ /dev/null @@ -1,35 +0,0 @@ -from tools.io import eGo - -ego = eGo(jsonpath='scenario_setting.json') - -ego.etrago_line_loading() -ego.etrago_network.plot() - -ego.edisgo_network - - -""" -Ausbau: -ego = eGo(jsonpath='scenario_setting.json') - - - -ego.etrago_network # Original eTraGo Network Klasse -ego.etrago.storage_charges # Aggregierte eGo Ergebnisse für etrago -ego.edisgo_network # Original eDisGo Network Klasse ??? -ego.edisgo # Aggregierte eGo Ergebnisse für edisgo -ego.total # eGo gesamt Ergebnisse über alle Spannungsebenen - - -""" -c = egoBasic(jsonpath='scenario_setting.json') - -c.edisgo_network -c.etrago_network - -b = eTraGoResults(jsonpath='scenario_setting.json') - - -b.etrago_network.plot_line_loading -b.etrago_network.plot_line_loading(b.etrago_network) -b.etrago.storage_charges From 37613d444af6ae97b705299cda63f757ee4b4ce5 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 10:14:01 +0200 Subject: [PATCH 122/314] update file --- ego/tools/utilities.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index 68de2a5d..c0726a5e 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -1,5 +1,4 @@ -""" -Utility functions of eGo +"""This module contains utility functions for the eGo application. """ import os @@ -18,7 +17,15 @@ def define_logging(log_name='ego.log'): """Helpers to log your modeling process with eGo and defines all settings. + Parameters + ---------- + log_name : str + Name of log file. Default: ``ego.log`` + Results + ------- + ego_logger : :obj:?? + Object of logging """ # ToDo: Logger should be set up more specific logging.basicConfig(level=logging.INFO) @@ -49,14 +56,21 @@ def define_logging(log_name='ego.log'): def get_scenario_setting(json_file='scenario_setting.json'): - """ Get and open json file with scenaio settings of eGo + """Get and open json file with scenaio settings of eGo. + The settings incluede global, eTraGo and eDisGo specific + settings of arguments and parameters for a reproducible + calculation. Parameters ---------- - - json_file (str): - default: 'scenario_setting.json' + json_file : str + Default: ``scenario_setting.json`` Name of scenario setting json file + + Results + ------- + scn_set : dict + Dictionary of json file """ path = os.getcwd() # add try ego/ @@ -87,17 +101,17 @@ def get_scenario_setting(json_file='scenario_setting.json'): return scn_set -def get_time_steps(args): +def get_time_steps(scn_set): """ Get time step of calculation by scenario settings. Parameters ---------- - args (dict): - dict of 'scenario_setting.json' + scn_set : dict + dict of ``scenario_setting.json`` Returns ------- - time_step (int): + time_step : int Number of timesteps of the calculation. """ From 3aa8ac79a857db7eba5fba81b95fa9283f35dd81 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 10:39:15 +0200 Subject: [PATCH 123/314] update file --- ego/tools/storages.py | 49 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 6f8747a0..913d9345 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -1,5 +1,4 @@ -""" -This file contains the eGo functions for studies on storages. +"""This module contains functions to summarize and studies on storages. """ __copyright__ = ("Europa-Universität Flensburg, " @@ -18,48 +17,48 @@ def total_storage_charges(network): - """ - Sum up the pysical storage values of the total scenario based on + """Sum up the pysical storage values of the total scenario based on eTraGo results. Parameters ---------- - network : eTraGo Network based on pypsa.network - PyPSA Network object modified by eTraGo - - plot (bool): - Use plot function - - - Returns + network : :class:`~.etrago.tools.io.NetworkScenario` + eTraGo ``NetworkScenario`` based on PyPSA Network. See also: + `pypsa.network `_ + Results ------- - - results : pandas.DataFrame - Return ... + results : :pandas:`pandas.DataFrame` + Summarize and returns a ``DataFrame`` of the storages optimaziation. Notes ----- - charge : + The ``results`` dataframe inclueds following parameters: + + charge : numeric Quantity of charged Energy in MWh over scenario time steps - discharge : + discharge : numeric Quantity of discharged Energy in MWh over scenario time steps - count : + count : int Number of storage units - p_nom_o_sum: + p_nom_o_sum: numeric Sum of optimal installed power capacity """ - charge = network.storage_units_t.p[network.storage_units_t. - p[network.storage_units[network.storage_units. - p_nom_opt > 0].index].values > 0.].\ - groupby(network.storage_units.carrier, axis=1).sum().sum() + charge = network.storage_units_t.\ + p[network.storage_units_t.p[network. + storage_units[network.storage_units. + p_nom_opt > 0].index]. + values > 0.].groupby(network.storage_units. + carrier, axis=1).sum().sum() discharge = network.storage_units_t.p[network.storage_units_t. - p[network.storage_units[network.storage_units. - p_nom_opt > 0].index].values < 0.].\ + p[network. + storage_units[network.storage_units. + p_nom_opt > 0]. + index].values < 0.].\ groupby(network.storage_units.carrier, axis=1).sum().sum() count = network.storage_units.bus[network.storage_units.p_nom_opt > 0].\ From 0bcdad1b51eeb00f347116138f4a01cd2133e00d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 10:41:37 +0200 Subject: [PATCH 124/314] update file --- ego/tools/storages.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 913d9345..7b48ec45 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -79,17 +79,18 @@ def total_storage_charges(network): def etrago_storages(network): - """Function for storage and grid expantion costs of eTraGo. + """Using function ``total_storage_charges`` for storage and grid expantion + costs of eTraGo. Parameters ---------- - - network : eTraGo Network - eTraGo Network Class based on PyPSA + network : :class:`~.etrago.tools.io.NetworkScenario` + eTraGo ``NetworkScenario`` based on PyPSA Network. See also: + `pypsa.network `_ Returns ------- - storages : pandas.DataFrame + storages : :pandas:`pandas.DataFrame` DataFrame with cumulated results of storages """ From 872237d56438e725583800d6b4e9c29fe129cbe5 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 10:51:09 +0200 Subject: [PATCH 125/314] update file --- ego/tools/results.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index 97d88b1b..40feded1 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- -""" -Module of eGo results with functions for writing, creating and results of eGo +"""This module include the results functions for analyze and creating results +based on eTraGo or eDisGo for eGo. + ToDo ---- - - add eDisGo - write results to database - - integrate plot and other functions ad methods to the class eGo """ From be7285d8afe3bd53551aac2f34cc30d4d9df0b3d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 10:57:06 +0200 Subject: [PATCH 126/314] update file --- ego/tools/results.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index 40feded1..b1c61a84 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -29,9 +29,20 @@ def create_etrago_results(network, scn_name): """ Create eTraGo results - Returns + Parameters + ---------- + network : :class:`~.etrago.tools.io.NetworkScenario` + eTraGo ``NetworkScenario`` based on PyPSA Network. See also: + `pypsa.network `_ + + scn_name : str + Name of used scenario + + + Results ------- - etrago : :obj:pd.DataFrame + etrago : :pandas:`pandas.DataFrame` + Results as DataFrame. """ From 56c2a5b028b5c378a7f5fcb13170317ba7a018c1 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 10:57:16 +0200 Subject: [PATCH 127/314] update file --- ego/tools/plots.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/ego/tools/plots.py b/ego/tools/plots.py index dc8609f9..b9492cc0 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -1,10 +1,9 @@ -""" -Module to collect useful functions for plotting results of eGo +"""Module which collects useful functions for plotting eTraGo, eDisGo and +eGo results. ToDo -- histogram -- etc. -- Implement plotly +---- +- Implement plotly for iplot """ __copyright__ = "tba" __license__ = "tba" @@ -37,13 +36,13 @@ # plot colore of Carriers def carriers_colore(): - """ - Return matplotlib colores per pypsa carrier of eTraGo + """ Return matplotlib colore set per carrier (technologies of + generators) of eTraGo. Returns -------- - :obj:`dict` : List of carriers and matplotlib colores - + ------- + colors : :obj:`dict` + List of carriers and matplotlib colores """ colors = {'biomass': 'green', @@ -71,6 +70,9 @@ def carriers_colore(): def make_all_plots(network): + """ Test function which run all ploting functions. + + """ # make a line loading plot plot_line_loading(network) @@ -92,8 +94,7 @@ def make_all_plots(network): def igeoplot(network, session, tiles=None, geoloc=None, args=None): - """ - Plot function in order to display eGo results on leaflet OSM map. + """Plot function in order to display eGo results on leaflet OSM map. This function will open the results in your main Webbrowser Parameters From 7acf4d690dfaadfe4c91c5cb02a565a946177d21 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 11:00:50 +0200 Subject: [PATCH 128/314] update file --- ego/tools/io.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 00b3bf6a..62f9b5b2 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -45,14 +45,14 @@ class egoBasic(object): """The eGo basic class select and creates based on your - `scenario_setting.json` file your definde eTraGo and + ``scenario_setting.json`` file your definde eTraGo and eDisGo results container. Parameters ---------- jsonpath : :obj:`json` - Path to _scenario_setting.json_ file. + Path to ``scenario_setting.json`` file. Results @@ -112,15 +112,14 @@ def __repr__(self): class eTraGoResults(egoBasic): - """eTraGo Results - - This module contains all results of eTraGo for eGo. + """The ``eTraGoResults`` class create and contains all results + of eTraGo and it's network container for eGo. Examples -------- - The module can be used by ``etg = eTraGoResults()`` + The module can be used by ``network = eTraGoResults()`` See also -------- From fc5756cdf2a7c296dc6cdc778aaac13afd9ee4e6 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 11:17:14 +0200 Subject: [PATCH 129/314] update file --- ego/tools/economics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index f055d223..8a24fdb8 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -1,5 +1,5 @@ """ -Module to collect useful functions for economic calculation of eGo which can +This module collects useful functions for economic calculation of eGo which can mainly distinguished in operational and investment costs. Todo: From b44b2b19104463c16724511aa0e4fb28a6e8fb3a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 11:26:16 +0200 Subject: [PATCH 130/314] update file --- ego/tools/storages.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 7b48ec45..c0048262 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -25,6 +25,7 @@ def total_storage_charges(network): network : :class:`~.etrago.tools.io.NetworkScenario` eTraGo ``NetworkScenario`` based on PyPSA Network. See also: `pypsa.network `_ + Results ------- results : :pandas:`pandas.DataFrame` From 6df29e6aac0a85a1a7ab012d988a5740be1bd6be Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:03:52 +0200 Subject: [PATCH 131/314] change to pep8 header style --- ego/ego_main.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 3872f902..a8f783e0 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -1,3 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description """ This is the application file for the tool eGo. The application eGo calculates the distribution and transmission grids of eTraGo and eDisGo. @@ -6,25 +25,20 @@ Note, that this Repository is under construction and relies on data provided by the OEDB. Currently, only members of the openego project team have access to this database. - """ -__copyright__ = ("Flensburg University of Applied Sciences, " - "Europa-Universität Flensburg, " - "Centre for Sustainable Energy Systems") -__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolf_bunke,maltesc" import pandas as pd import os - from ego.tools.utilities import define_logging logger = define_logging(log_name='ego.log') - +# if not 'READTHEDOCS' in os.environ: from ego.tools.io import eGo -# if not 'READTHEDOCS' in os.environ: -# from tools.io import eGo -#from etrago.tools.io import results_to_oedb +__copyright__ = ("Flensburg University of Applied Sciences, " + "Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke,maltesc" if __name__ == '__main__': From cdaf5e64a62c5e92191dc90760396e74997fb962 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:06:25 +0200 Subject: [PATCH 132/314] add pep8 header style --- ego/tools/specs.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ego/tools/specs.py b/ego/tools/specs.py index 6fc10300..45eb4ecb 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -1,3 +1,24 @@ +# -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description +""" +""" # Import # General Packages import os @@ -12,6 +33,12 @@ import logging logger = logging.getLogger('ego') +__copyright__ = ("Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke,maltesc" + + # Functions From 4da0625e041c16eaa6dd3bdabae9580aa1c4e97d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:06:36 +0200 Subject: [PATCH 133/314] change to pep8 header style --- ego/tools/storages.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index c0048262..8797a5ff 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -1,11 +1,25 @@ +# -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description """This module contains functions to summarize and studies on storages. """ -__copyright__ = ("Europa-Universität Flensburg, " - "Centre for Sustainable Energy Systems") -__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolf_bunke,maltesc" - import io import os import logging @@ -15,6 +29,11 @@ import pandas as pd import numpy as np +__copyright__ = ("Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke,maltesc" + def total_storage_charges(network): """Sum up the pysical storage values of the total scenario based on From bbe8f47f91464b7f871d09888817cdef89a63467 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:06:47 +0200 Subject: [PATCH 134/314] change to pep8 header style --- ego/tools/utilities.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index c0726a5e..8053e60f 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -1,12 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description """This module contains utility functions for the eGo application. - """ import os import pandas as pd import json import logging - __copyright__ = ("Flensburg University of Applied Sciences, " "Europa-Universität Flensburg, " "Centre for Sustainable Energy Systems") From 44e9beecce7ad82bc4d6dbbc245c8386a9a771c8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:08:03 +0200 Subject: [PATCH 135/314] change to pep8 header style --- ego/tools/results.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index b1c61a84..9b441e32 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -1,18 +1,31 @@ # -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description """This module include the results functions for analyze and creating results based on eTraGo or eDisGo for eGo. - ToDo ---- - write results to database """ -__copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ - "Flensburg, Centre for Sustainable Energy Systems" -__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolfbunke" import io import os @@ -24,6 +37,11 @@ import numpy as np from tools.economics import get_generator_investment +__copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ + "Flensburg, Centre for Sustainable Energy Systems" +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolfbunke" + def create_etrago_results(network, scn_name): """ From 8c83b2491f99b1c38ac3ca9bbf70450e0b6a179c Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:08:17 +0200 Subject: [PATCH 136/314] change to pep8 header style --- ego/tools/results.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index 9b441e32..ced17ec4 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -23,8 +23,6 @@ ToDo ---- - write results to database - - """ import io From e1a379a225044580b1c63a847e446474bbb8206f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:11:55 +0200 Subject: [PATCH 137/314] pep8 --- ego/tools/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ego/tools/__init__.py b/ego/tools/__init__.py index 3ecdf3c8..c28ee935 100644 --- a/ego/tools/__init__.py +++ b/ego/tools/__init__.py @@ -1,3 +1,6 @@ +""" +""" + __copyright__ = "Europa-Universität Flensburg, Centre for Sustainable Energy Systems" __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" __author__ = "wolf_bunke" From 99c97828dfe06796b5710b1b93770736187cf48d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:12:09 +0200 Subject: [PATCH 138/314] change to pep8 header style --- ego/tools/economics.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 8a24fdb8..c25728be 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -1,12 +1,30 @@ -""" -This module collects useful functions for economic calculation of eGo which can +# -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description +"""This module collects useful functions for economic calculation of eGo which can mainly distinguished in operational and investment costs. Todo: 1) Investment costs of eTrago and eDisGo 2) Total system costs - """ + import io import os import logging @@ -16,8 +34,14 @@ import pandas as pd import numpy as np +__copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ + "Flensburg, Centre for Sustainable Energy Systems" +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolfbunke" # calculate annuity per time step or periode + + def annuity_per_period(capex, n, wacc, t): """ Parameters From 216122dcb7490b911579ce1ac1727f6963ddf742 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:12:15 +0200 Subject: [PATCH 139/314] change to pep8 header style --- ego/tools/io.py | 62 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 62f9b5b2..ee3bfd77 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -1,14 +1,25 @@ -""" -This file contains the eGo main class as well as input & output functions +# -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description +"""This file contains the eGo main class as well as input & output functions of eGo in order to build the eGo application container. - """ - -__copyright__ = ("Europa-Universität Flensburg, " - "Centre for Sustainable Energy Systems") -__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolf_bunke,maltesc" - import sys import os import logging @@ -16,7 +27,6 @@ import pandas as pd import numpy as np - if not 'READTHEDOCS' in os.environ: import pyproj as proj import geopandas as gpd @@ -39,9 +49,16 @@ from egoio.db_tables import model_draft, grid from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, curtailment, gen_dist, storage_distribution, - plot_voltage, plot_residual_load) + plot_voltage, plot_residual_load, + plot_line_loading_diff, full_load_hours, + extension_overlay_network) from etrago.appl import etrago +__copyright__ = ("Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke,maltesc" + class egoBasic(object): """The eGo basic class select and creates based on your @@ -203,6 +220,29 @@ def etrago_residual_load(self, **kwargs): """ return plot_residual_load(network=self.etrago_network, **kwargs) + def etrago_line_loading_diff(self, networkB, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return plot_line_loading_diff(networkA=self.etrago_network, + networkB=networkB, **kwargs) + + def etrago_extension_overlay_network(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return extension_overlay_network(network=self.etrago_network, + **kwargs) + + def etrago_full_load_hours(self, **kwargs): + """ + Integrate function from eTraGo. + For more information see: + """ + return full_load_hours(network=self.etrago_network, **kwargs) + # add other methods from eTraGo here From 70aea89d4185f6c865807bd1e97392adb347cc0a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 12:12:21 +0200 Subject: [PATCH 140/314] change to pep8 header style --- ego/tools/plots.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/ego/tools/plots.py b/ego/tools/plots.py index b9492cc0..6fbed535 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -1,3 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description """Module which collects useful functions for plotting eTraGo, eDisGo and eGo results. @@ -5,10 +24,6 @@ ---- - Implement plotly for iplot """ -__copyright__ = "tba" -__license__ = "tba" -__author__ = "tba" - import numpy as np import pandas as pd import os @@ -33,6 +48,11 @@ import logging logger = logging.getLogger('ego') +__copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ + "Flensburg, Centre for Sustainable Energy Systems" +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolfbunke" + # plot colore of Carriers def carriers_colore(): From 79efb2058187aa06e0f32f7b6e81c3a2aa999e5e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 13:22:10 +0200 Subject: [PATCH 141/314] update file --- ego/tools/utilities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index 8053e60f..4a8b4d40 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -41,8 +41,8 @@ def define_logging(log_name='ego.log'): Results ------- - ego_logger : :obj:?? - Object of logging + ego_logger : :class:`logging.basicConfig`. + Set up ``ego_logger`` object of package ``logging`` """ # ToDo: Logger should be set up more specific logging.basicConfig(level=logging.INFO) From f2dedbc489195e2c19c762812d34db7eb7ba3857 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 13:25:31 +0200 Subject: [PATCH 142/314] update file --- ego/tools/utilities.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index 4a8b4d40..2dc9ed8a 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -37,7 +37,8 @@ def define_logging(log_name='ego.log'): Parameters ---------- log_name : str - Name of log file. Default: ``ego.log`` + Name of log file. Default: ``ego.log``. + Results ------- From 0aa4a93539058ac64a26e968d8cfae636e7d174d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 13:35:44 +0200 Subject: [PATCH 143/314] update file --- ego/tools/storages.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 8797a5ff..0cae1ac3 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -41,7 +41,7 @@ def total_storage_charges(network): Parameters ---------- - network : :class:`~.etrago.tools.io.NetworkScenario` + network : :etrago:`etrago.tools.io.NetworkScenario` eTraGo ``NetworkScenario`` based on PyPSA Network. See also: `pypsa.network `_ From c0e08ea33603c273cb713439deb9099e814a3d63 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 13:36:19 +0200 Subject: [PATCH 144/314] add new functions wip --- ego/tools/results.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index ced17ec4..5eb87bce 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -41,7 +41,7 @@ __author__ = "wolfbunke" -def create_etrago_results(network, scn_name): +def create_etrago_results(network, scn_name): # rename function """ Create eTraGo results @@ -99,5 +99,26 @@ def create_etrago_results(network, scn_name): return etrago +def results_per_voltage(network): + """Get eTraGo results per voltage level + + Parameters + ---------- + network : :etrago:`etrago.tools.io.NetworkScenario` + eTraGo ``NetworkScenario`` based on PyPSA Network. See also: + `pypsa.network `_ + + + """ + + +def ego_results_to_oedb(total): + """ ToDo: Funtion to upload results into oedb database + + """ + + pass + + if __name__ == '__main__': pass From 2180ae82bda122c53713cd596483fd28c1a8b5b9 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 14:02:47 +0200 Subject: [PATCH 145/314] add more packages to meth links --- doc/conf.py | 8 +++++++- ego/tools/results.py | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 162ac2cb..2b095290 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -409,7 +409,13 @@ def __getattr__(cls, name): # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} +intersphinx_mapping = {'python': ('https://docs.python.org/3', None), + 'etrago': ('https://etrago.readthedocs.io/en/latest' + ), None), + 'edisgo': ('http://edisgo.readthedocs.io/en/dev',None),) + 'ding0': ('https://dingo.readthedocs.io/en/dev',None), + 'pypsa': ('https://pypsa.org/doc/',None), + } # Numbered figures numfig = True diff --git a/ego/tools/results.py b/ego/tools/results.py index 5eb87bce..96ae5b4e 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -113,7 +113,7 @@ def results_per_voltage(network): def ego_results_to_oedb(total): - """ ToDo: Funtion to upload results into oedb database + """ ToDo: Function to upload results into oedb database """ From ecb3b5c06d15b499f35638eadc6cf16449f419d3 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 14:06:09 +0200 Subject: [PATCH 146/314] testing meth for etrago --- ego/tools/results.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ego/tools/results.py b/ego/tools/results.py index 96ae5b4e..df298a86 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -108,6 +108,24 @@ def results_per_voltage(network): eTraGo ``NetworkScenario`` based on PyPSA Network. See also: `pypsa.network `_ + Results + ------- + + Test + :meth:`apply ` + :meth:`pandas:pandas.DataFrame.apply` + :meth:`pandas.DataFrame.apply` + + + and + :meth:`apply ` + :meth:`etrago:etrago.appl.etrago` + :meth:`etrago.appl.etrago` + + + + + """ From 8a8cec095198d723fc26d278b265c0efdfe0ef31 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 14:08:13 +0200 Subject: [PATCH 147/314] update file --- doc/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 2b095290..7dda523a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -410,8 +410,8 @@ def __getattr__(cls, name): # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'python': ('https://docs.python.org/3', None), - 'etrago': ('https://etrago.readthedocs.io/en/latest' - ), None), + 'etrago': ('https://etrago.readthedocs.io/en/latest', + None), 'edisgo': ('http://edisgo.readthedocs.io/en/dev',None),) 'ding0': ('https://dingo.readthedocs.io/en/dev',None), 'pypsa': ('https://pypsa.org/doc/',None), From ede3089eecd8f9fdd698813a58e0f43dc0cf090d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 14:15:14 +0200 Subject: [PATCH 148/314] update file --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 7dda523a..763e37dd 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -412,7 +412,7 @@ def __getattr__(cls, name): intersphinx_mapping = {'python': ('https://docs.python.org/3', None), 'etrago': ('https://etrago.readthedocs.io/en/latest', None), - 'edisgo': ('http://edisgo.readthedocs.io/en/dev',None),) + 'edisgo': ('http://edisgo.readthedocs.io/en/dev',None), 'ding0': ('https://dingo.readthedocs.io/en/dev',None), 'pypsa': ('https://pypsa.org/doc/',None), } From 56439fddee1731ebe60d5564d5ad8ad8578597a8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 14:22:39 +0200 Subject: [PATCH 149/314] update file --- doc/developer.rst | 34 ++++++++++++++++++++++++++++++++++ ego/tools/results.py | 18 +----------------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/doc/developer.rst b/doc/developer.rst index 11a0a144..9a0d784e 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -54,3 +54,37 @@ Change of units from Mega to kilo: :file: storage_units.csv :delim: , :header-rows: 1 + + +testing zone +============ + + +:ref:`apply ` +:ref:`apply ` +:ref:`apply ` +:ref:`apply ` +:ref:`apply ` +:ref:`apply ` +:meth:`apply ` +:meth:`pandas:pandas.dataframe.apply` +:meth:`pandas.dataframe.apply` + + +Test +:meth:`apply ` +:meth:`pandas:pandas.DataFrame.apply` +:meth:`pandas.DataFrame.apply` + + +and +:meth:`apply ` +:meth:`etrago:etrago.appl.etrago` +:meth:`etrago.appl.etrago` + + +:ref:`etrago ` + :ref:`etrago ` + + + diff --git a/ego/tools/results.py b/ego/tools/results.py index df298a86..c7b478d9 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -104,29 +104,13 @@ def results_per_voltage(network): Parameters ---------- - network : :etrago:`etrago.tools.io.NetworkScenario` + network : :etrago:`etrago.tools.io.NetworkScenario` eTraGo ``NetworkScenario`` based on PyPSA Network. See also: `pypsa.network `_ Results ------- - Test - :meth:`apply ` - :meth:`pandas:pandas.DataFrame.apply` - :meth:`pandas.DataFrame.apply` - - - and - :meth:`apply ` - :meth:`etrago:etrago.appl.etrago` - :meth:`etrago.appl.etrago` - - - - - - """ From e5d95feb3f11761162390462c3a95713c9a56145 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 14:33:09 +0200 Subject: [PATCH 150/314] update file --- ego/tools/results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index c7b478d9..eb806bb5 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -104,7 +104,7 @@ def results_per_voltage(network): Parameters ---------- - network : :etrago:`etrago.tools.io.NetworkScenario` + network : :class:`etrago.tools.io.NetworkScenario>` eTraGo ``NetworkScenario`` based on PyPSA Network. See also: `pypsa.network `_ From e24db4b62eda54f1109bc613803e45af6862c53f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 14:35:17 +0200 Subject: [PATCH 151/314] update file --- ego/tools/results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index eb806bb5..63bf772d 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -104,7 +104,7 @@ def results_per_voltage(network): Parameters ---------- - network : :class:`etrago.tools.io.NetworkScenario>` + network : :class:`etrago.tools.io.NetworkScenario` eTraGo ``NetworkScenario`` based on PyPSA Network. See also: `pypsa.network `_ From 9c4b051a75d0569b6e2e9639ec703d9730ab0b27 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 6 Jul 2018 14:36:17 +0200 Subject: [PATCH 152/314] update file --- doc/developer.rst | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/doc/developer.rst b/doc/developer.rst index 9a0d784e..7f91582b 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -60,31 +60,40 @@ testing zone ============ +ref pandas +---------- + :ref:`apply ` :ref:`apply ` :ref:`apply ` :ref:`apply ` :ref:`apply ` :ref:`apply ` + +meth pandas +----------- + :meth:`apply ` :meth:`pandas:pandas.dataframe.apply` :meth:`pandas.dataframe.apply` -Test -:meth:`apply ` -:meth:`pandas:pandas.DataFrame.apply` -:meth:`pandas.DataFrame.apply` - +Test etrago +----------- -and :meth:`apply ` :meth:`etrago:etrago.appl.etrago` :meth:`etrago.appl.etrago` - +ref etrago +---------- + :ref:`etrago ` - :ref:`etrago ` +:ref:`etrago ` + +The :meth:` etrago() method ` creates your ``network``. + + From 643bb34d87e39027ad392cb3bab4e1f8b3ebac4e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 9 Jul 2018 14:11:57 +0200 Subject: [PATCH 153/314] update file --- doc/index.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 6c150f01..6176d9d3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -2,8 +2,13 @@ Welcome to eGo documentation! ============================= +.. note:: Note, this software is under construction and not + ready for a normal use. - +.. note:: Note, currently the data source of eGo relies on + the Open Energy Database. - The registration for the public + accessible API can be found on + `openenergy-platform.org/login `_. .. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 @@ -23,14 +28,9 @@ Welcome to eGo documentation! api - -Take also a look into the Documentation of `eTraGo `_ and `eDisGo `_ which are part of eGo. - - - -.. note:: Note, this software is under construction and not ready for a normal use. - -.. warning:: Note, currently the data source of eGo relies on - the Open Energy Database - has no public accessible API, yet. Thus, currently you won't be able to run eGo without modifications. +Take also a look into the Documentation of +`eTraGo `_ and +`eDisGo `_ which are part of eGo. From 9f4e6bff043034a86246496d985acc73c21ad6ff Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 9 Jul 2018 14:12:11 +0200 Subject: [PATCH 154/314] update test --- doc/developer.rst | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/doc/developer.rst b/doc/developer.rst index 7f91582b..331756dc 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -8,7 +8,7 @@ Developer notes Interface eDisGo for grid and storage costs -------------------------------------------- +=========================================== .. code-block:: python @@ -40,12 +40,13 @@ eDisGo units Definition of grid expansion costs -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +================================== `grid expansion costs `_ Definition of storage exansion -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +------------------------------ + `Attributes according to PyPSA `_ Change of units from Mega to kilo: @@ -54,9 +55,9 @@ Change of units from Mega to kilo: :file: storage_units.csv :delim: , :header-rows: 1 - - -testing zone + + +Testing zone ============ @@ -86,14 +87,9 @@ Test etrago :meth:`etrago.appl.etrago` ref etrago ----------- +---------- :ref:`etrago ` -:ref:`etrago ` - -The :meth:` etrago() method ` creates your ``network``. - - - - - +:ref:`etrago ` + +The :meth:`etrago() method ` creates your ``network``. From d45bcf027ac208c13687315c93bf35ddddde16ec Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 9 Jul 2018 14:26:25 +0200 Subject: [PATCH 155/314] changed etrago_ and edisgo_network to single classes --- ego/tools/io.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index ee3bfd77..6a4d2397 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -91,9 +91,6 @@ def __init__(self, self.jsonpath = 'scenario_setting.json' self.json_file = get_scenario_setting(self.jsonpath) - # self.etrago_network = None - self.edisgo_network = None - # Database connection from json_file try: conn = db.connection(section=self.json_file['global']['db']) @@ -106,14 +103,6 @@ def __init__(self, # get scn_name self.scn_name = self.json_file['eTraGo']['scn_name'] - if self.json_file['global']['eTraGo'] is True: - logger.info('Create eTraGo network') - self.etrago_network = etrago(self.json_file['eTraGo']) - - if self.json_file['global']['eDisGo'] is True: - logger.info('Create eDisGo network') - self.edisgo_network = None # add eDisGo initialisation here - pass def __repr__(self): @@ -155,6 +144,13 @@ def __init__(self, jsonpath, *args, **kwargs): super(eTraGoResults, self).__init__(self, jsonpath, *args, **kwargs) + self.etrago_network = None + + # create eTraGo NetworkScenario network + if self.json_file['global']['eTraGo'] is True: + logger.info('Create eTraGo network') + self.etrago_network = etrago(self.json_file['eTraGo']) + # add selected results to Results container self.etrago = pd.DataFrame() self.etrago.generator = pd.DataFrame() @@ -164,6 +160,7 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago_network) self.etrago.generator = create_etrago_results(self.etrago_network, self.scn_name) + # add functions direct # self.etrago_network.etrago_line_loading = etrago_line_loading @@ -261,10 +258,17 @@ class eDisGoResults(egoBasic): def __init__(self, jsonpath, *args, **kwargs): super(eDisGoResults, self).__init__(self, jsonpath, *args, **kwargs) + self.edisgo_network = None self.edisgo = pd.DataFrame() + if self.json_file['global']['eDisGo'] is True: + logger.info('Create eDisGo network') + self.edisgo_network = None # add eDisGo initialisation here + pass + pass + class eGo(eTraGoResults, eDisGoResults): """Main eGo module which including all results and main functionalities. From 18d9566302e7a9f416c38f341d327043294ba349 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 9 Jul 2018 14:41:18 +0200 Subject: [PATCH 156/314] change order of image import --- doc/index.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 6176d9d3..29270e93 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -2,6 +2,10 @@ Welcome to eGo documentation! ============================= +.. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 + :align: right + :scale: 100% + .. note:: Note, this software is under construction and not ready for a normal use. @@ -11,9 +15,6 @@ Welcome to eGo documentation! `openenergy-platform.org/login `_. -.. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 - :align: right - :scale: 100% .. toctree:: From 42b8942664ec335b4845f0628844c117f2e88f81 Mon Sep 17 00:00:00 2001 From: maltesc Date: Mon, 9 Jul 2018 14:45:03 +0200 Subject: [PATCH 157/314] new integration class --- ego/tools/edisgo_integration.py | 136 ++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 ego/tools/edisgo_integration.py diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py new file mode 100644 index 00000000..48bb958a --- /dev/null +++ b/ego/tools/edisgo_integration.py @@ -0,0 +1,136 @@ +""" +This file is part of the the eGo toolbox. +It contains the class definition for multiple eDisGo networks and results. + +""" +__copyright__ = ("Flensburg University of Applied Sciences, " + "Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke,maltesc" + +# Import +## Local Packages + +## Project Packages +from egoio.db_tables import model_draft, grid +from egoio.tools import db +from edisgo.tools.edisgo_run import ( + run_edisgo_basic + ) + +## Other Packages +from sqlalchemy.orm import sessionmaker + +class EDisGoNetworks: + """ + Represents multiple eDisGo networks + + """ + + def __init__(self, **kwargs): + + conn = db.connection(section='oedb') + Session = sessionmaker(bind=conn) + self._session = Session() + + self._json_file = kwargs.get('json_file', None) + + self._grid_version = self._json_file['global']['gridversion'] + self._edisgo_args = self._json_file['eDisGo'] + + if self._grid_version is not None: + self._versioned = True + else: + self._versioned = False + + self._etrago_network = kwargs.get('etrago_network', None) + + + def run_edisgo(self, **kwargs): + + + run_edisgo_basic() + + # Hier implementieren, so wie twice, aber mit etrago. + # Reinforce mit Status quo worst case + # specs klasse umgehen! + raise NotImplementedError + + +## Helpful tools + def get_mv_grid_from_bus_id(self, bus_id): + """ + Returns the MV grid ID for a given eTraGo bus + + """ + + if self._versioned is True: + ormclass_hvmv_subst = grid.__getattribute__( + 'EgoDpHvmvSubstation' + ) + subst_id = self._session.query( + ormclass_hvmv_subst.subst_id + ).filter( + ormclass_hvmv_subst.otg_id == bus_id, + ormclass_hvmv_subst.version == self._grid_version + ).scalar() + + if self._versioned is False: + ormclass_hvmv_subst = model_draft.__getattribute__( + 'EgoGridHvmvSubstation' + ) + subst_id = self._session.query( + ormclass_hvmv_subst.subst_id + ).filter( + ormclass_hvmv_subst.otg_id == bus_id + ).scalar() + + return subst_id + + def get_bus_id_from_mv_grid(self, subst_id): + """ + Returns the eTraGo bus ID for a given MV grid + + """ + if self._versioned is True: + ormclass_hvmv_subst = grid.__getattribute__( + 'EgoDpHvmvSubstation' + ) + bus_id = self._session.query( + ormclass_hvmv_subst.otg_id + ).filter( + ormclass_hvmv_subst.subst_id == subst_id, + ormclass_hvmv_subst.version == self._grid_version + ).scalar() + + if self._versioned is False: + ormclass_hvmv_subst = model_draft.__getattribute__( + 'EgoGridHvmvSubstation' + ) + bus_id = self._session.query( + ormclass_hvmv_subst.otg_id + ).filter( + ormclass_hvmv_subst.subst_id == subst_id + ).scalar() + + return bus_id + + def get_hvmv_translation(self): + raise NotImplementedError + + + # Hier clustering usw. + + + + + + +#test = EDisGoNetworks(ego.session, json_file=ego.json_file) +# +#test._edisgo_args +#test._session +#t = test.get_mv_grid_from_bus_id(25214) +#test.get_bus_id_from_mv_grid(168) +#print(t) From 1b31130de6593d2c678a355f04164126c3c4d896 Mon Sep 17 00:00:00 2001 From: maltesc Date: Mon, 9 Jul 2018 17:13:02 +0200 Subject: [PATCH 158/314] specs integration --- ego/ego_main.py | 2 +- ego/scenario_setting.json | 4 +- ego/tools/edisgo_integration.py | 91 ++++++++++++++++++++++++++++++--- ego/tools/io.py | 22 ++++---- ego/tools/specs.py | 78 ++++++++++++++-------------- 5 files changed, 138 insertions(+), 59 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index a8f783e0..0a8294d5 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -47,7 +47,7 @@ logger.info('Start calculation') ego = eGo(jsonpath='scenario_setting.json') - ego.etrago_line_loading() +# ego.etrago_line_loading() """ diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 0424d6b8..e2d6212e 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -25,7 +25,7 @@ "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": 20, + "network_clustering_kmeans": false, "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, @@ -38,6 +38,8 @@ }, "eDisGo": { "specs": true, + "ding0_files": "data/MV_grids/20180705104811", + "scn_name": "NEP 2035", "comments": "make a comment" } } diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 48bb958a..e7257c38 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -15,13 +15,21 @@ ## Project Packages from egoio.db_tables import model_draft, grid from egoio.tools import db +from edisgo.grid.network import Results from edisgo.tools.edisgo_run import ( run_edisgo_basic ) +from ego.tools.specs import (get_etragospecs_direct) ## Other Packages +import os +import logging from sqlalchemy.orm import sessionmaker +# Logging +logging.basicConfig(format='%(asctime)s %(message)s',level=logging.INFO) +logger = logging.getLogger(__name__) + class EDisGoNetworks: """ Represents multiple eDisGo networks @@ -39,24 +47,84 @@ def __init__(self, **kwargs): self._grid_version = self._json_file['global']['gridversion'] self._edisgo_args = self._json_file['eDisGo'] + self._ding0_files = self._edisgo_args['ding0_files'] + self._scn_name = self._edisgo_args['scn_name'] + + if self._scn_name == 'Status Quo': + self._generator_scn = None + if self._scn_name == 'NEP 2035': + self._generator_scn = 'nep2035' + elif self._scn_name == 'eGo100': + raise NotImplementedError + if self._grid_version is not None: self._versioned = True else: self._versioned = False self._etrago_network = kwargs.get('etrago_network', None) + - - def run_edisgo(self, **kwargs): + def check_available_mv_grids(self): + + mv_grids = [] + for file in os.listdir(self._ding0_files): + if file.endswith('.pkl'): + mv_grids.append( + int(file.replace( + 'ding0_grids__', '' + ).replace('.pkl', ''))) + + return mv_grids - run_edisgo_basic() + def run_edisgo(self, mv_grid_id): + """ + Runs eDisGo with the desired settings - # Hier implementieren, so wie twice, aber mit etrago. - # Reinforce mit Status quo worst case - # specs klasse umgehen! - raise NotImplementedError + """ + + bus_id = self.get_bus_id_from_mv_grid(mv_grid_id) + + specs = get_etragospecs_direct( + self._session, + bus_id, + self._etrago_network, + self._scn_name) + return specs + +# ding0_filepath = ( +# self._ding0_files +# + '/ding0_grids__' +# + str(mv_grid_id) +# + '.pkl') +# +# if not os.path.isfile(ding0_filepath): +# msg = 'Not MV grid file for MV grid ID: ' + str(mv_grid_id) +# logger.error(msg) +# raise Exception(msg) +# +# + +# ### Base case with no generator import (initial reinforcement) +# edisgo_grid, \ +# costs_before_geno_import, \ +# grid_issues_before_geno_import = run_edisgo_basic( +# ding0_filepath=ding0_filepath, +# generator_scenario=None, +# analysis='worst-case') +# +# ### Second run for corresponding scenario +# edisgo_grid.network.results = Results() +# edisgo_grid.network.pypsa = None +# +# if self._generator_scn: +# edisgo_grid.import_generators( +# generator_scenario=self._generator_scn) + + + ## Helpful tools def get_mv_grid_from_bus_id(self, bus_id): @@ -127,9 +195,16 @@ def get_hvmv_translation(self): -#test = EDisGoNetworks(ego.session, json_file=ego.json_file) +test = EDisGoNetworks( + json_file=ego.json_file, + etrago_network=ego.etrago_network) + # #test._edisgo_args +ed = test.run_edisgo(mv_grid_id=1729) +# +#ed.network.results.equipment_changes + #test._session #t = test.get_mv_grid_from_bus_id(25214) #test.get_bus_id_from_mv_grid(168) diff --git a/ego/tools/io.py b/ego/tools/io.py index 54b403d1..394b945a 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -153,17 +153,17 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago_network = etrago(self.json_file['eTraGo']) # add selected results to Results container - self.etrago = pd.DataFrame() - self.etrago.generator = pd.DataFrame() - self.etrago.storage_charges = total_storage_charges(self.etrago_network) - self.etrago.storage_costs = etrago_storages(self.etrago_network) - self.etrago.operating_costs = etrago_operating_costs( - self.etrago_network) - self.etrago.generator = create_etrago_results(self.etrago_network, - self.scn_name) - - # add functions direct - # self.etrago_network.etrago_line_loading = etrago_line_loading + self.etrago = pd.DataFrame() + self.etrago.generator = pd.DataFrame() + self.etrago.storage_charges = total_storage_charges(self.etrago_network) + self.etrago.storage_costs = etrago_storages(self.etrago_network) + self.etrago.operating_costs = etrago_operating_costs( + self.etrago_network) + self.etrago.generator = create_etrago_results(self.etrago_network, + self.scn_name) + + # add functions direct + # self.etrago_network.etrago_line_loading = etrago_line_loading pass diff --git a/ego/tools/specs.py b/ego/tools/specs.py index 4b55a940..b1fd08b6 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -389,8 +389,8 @@ def get_etragospecs_direct(session, bus_id, - eTraGo, - args): + etrago_network, + scn_name): """ Reads eTraGo Results from Database and returns an Object of the Interface class ETraGoSpecs @@ -416,28 +416,30 @@ def get_etragospecs_direct(session, specs_meta_data.update({'TG Bus ID': bus_id}) - ormclass_result_meta = model_draft.__getattribute__('EgoGridPfHvResultMeta') +# ormclass_result_meta = model_draft.__getattribute__('EgoGridPfHvResultMeta') ormclass_aggr_w = model_draft.__getattribute__( 'ego_supply_aggr_weather_mview') + logger.warning('Weather table taken from model_draft') ormclass_source = model_draft.__getattribute__('EgoGridPfHvSource') + logger.warning('Source table taken from model_draft') - snap_idx = eTraGo.snapshots - - # If the results are beeing recovered, the scn_name cannot be used from Scenario Settings File - if args['global']['recover'] == True: - result_id = args['global']['result_id'] - scn_name = session.query( - ormclass_result_meta.scn_name - ).filter( - ormclass_result_meta.result_id == result_id - ).scalar( - ) - else: - scn_name = args['eTraGo']['scn_name'] - specs_meta_data.update({'scn_name': scn_name}) + snap_idx = etrago_network.snapshots - if scn_name == 'SH Status Quo': - scn_name = 'Status Quo' +# # If the results are beeing recovered, the scn_name cannot be used from Scenario Settings File +# if args['global']['recover'] == True: +# result_id = args['global']['result_id'] +# scn_name = session.query( +# ormclass_result_meta.scn_name +# ).filter( +# ormclass_result_meta.result_id == result_id +# ).scalar( +# ) +# else: +# scn_name = args['eTraGo']['scn_name'] +# specs_meta_data.update({'scn_name': scn_name}) +# +# if scn_name == 'SH Status Quo': +# scn_name = 'Status Quo' # Generators t0 = time.perf_counter() @@ -445,7 +447,7 @@ def get_etragospecs_direct(session, weather_dpdnt = ['wind', 'solar'] # DF procesing - all_gens_df = eTraGo.generators[eTraGo.generators['bus'] == str(bus_id)] + all_gens_df = etrago_network.generators[etrago_network.generators['bus'] == str(bus_id)] all_gens_df.reset_index(inplace=True) all_gens_df = all_gens_df.rename(columns={'index': 'generator_id'}) all_gens_df = all_gens_df[['generator_id', 'p_nom', 'p_nom_opt', 'carrier']] @@ -479,7 +481,7 @@ def get_etragospecs_direct(session, for index, row in conv_df.iterrows(): generator_id = row['generator_id'] source = row['name'] - p = eTraGo.generators_t.p[str(generator_id)] + p = etrago_network.generators_t.p[str(generator_id)] p_norm = p / conv_cap[source]['p_nom'] conv_dsptch_norm[source] = conv_dsptch_norm[source] + p_norm @@ -535,10 +537,10 @@ def get_etragospecs_direct(session, aggr_gens[aggr_gens['ren_id'] == ren_id]['p_nom_aggr']) p_nom = float(ren_df[ren_df['generator_id'] == gen_id]['p_nom']) - p_series = eTraGo.generators_t.p[str(gen_id)] + p_series = etrago_network.generators_t.p[str(gen_id)] p_norm_tot_series = p_series / p_nom_aggr - p_max_pu_series = eTraGo.generators_t.p_max_pu[str(gen_id)] + p_max_pu_series = etrago_network.generators_t.p_max_pu[str(gen_id)] p_max_norm_tot_series = p_max_pu_series * p_nom / p_nom_aggr p_curt_norm_tot_series = p_max_norm_tot_series - p_norm_tot_series @@ -550,7 +552,7 @@ def get_etragospecs_direct(session, t3 = time.perf_counter() performance.update({'Renewable Dispatch and Curt.': t3-t2}) # Capactiy - stor_df = eTraGo.storage_units[eTraGo.storage_units['bus'] == str(bus_id)] + stor_df = etrago_network.storage_units[etrago_network.storage_units['bus'] == str(bus_id)] stor_df.reset_index(inplace=True) stor_df = stor_df.rename(columns={'index': 'storage_id'}) stor_df = stor_df[[ @@ -598,7 +600,7 @@ def get_etragospecs_direct(session, name = row['name'] stor_id = row['storage_id'] if name == 'battery': - stor_series = eTraGo.storage_units_t.p[str(stor_id)] + stor_series = etrago_network.storage_units_t.p[str(stor_id)] stor_series_kW = stor_series * 1000 battery_active_power = battery_active_power + stor_series_kW @@ -634,16 +636,16 @@ def get_etragospecs_direct(session, return specs -def get_mvgrid_from_bus_id(session, - bus_id): - # Mapping - ormclass_hvmv_subst = model_draft.__getattribute__('EgoGridHvmvSubstation') - subst_id = session.query( - ormclass_hvmv_subst.subst_id - ).filter( - ormclass_hvmv_subst.otg_id == bus_id - ).scalar( - ) - # ToDo Check if subst_id is really the mv grid ID - # Anyway, this should be adapted by Dingo - return subst_id +#def get_mvgrid_from_bus_id(session, +# bus_id): +# # Mapping +# ormclass_hvmv_subst = model_draft.__getattribute__('EgoGridHvmvSubstation') +# subst_id = session.query( +# ormclass_hvmv_subst.subst_id +# ).filter( +# ormclass_hvmv_subst.otg_id == bus_id +# ).scalar( +# ) +# # ToDo Check if subst_id is really the mv grid ID +# # Anyway, this should be adapted by Dingo +# return subst_id From 46e05ad41e073fb3f4466be5dcc2b653f512c6f2 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 14:22:15 +0200 Subject: [PATCH 159/314] add edisgo_convert_capital_costs function WIP --- ego/tools/economics.py | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index c25728be..ef36eb98 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -66,6 +66,27 @@ def annuity_per_period(capex, n, wacc, t): return capex * (wacc * (1 + wacc) ** n) / ((1 + wacc) ** n - 1) +def edisgo_convert_capital_costs(): + """ + + Parameters + ---------- + + grid_components : :obj:dict + Dictionary of ding0 grid components which are extendable + (Name, investment_cost, lifetime) + json_file : :obj:dict + Dictionary of the ``scenario_setting.json`` file + + + """ + # eTraGo calculation in + # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 + # def convert_capital_costs(network, start_snapshot, end_snapshot, + # p=0.05, T=40): + # Define function + + def etrago_operating_costs(network): """ Function to get all operating costs of eTraGo. @@ -124,7 +145,7 @@ def etrago_operating_costs(network): return power_price -def etrago_grid_investment(network): +def etrago_grid_investment(network, json_file): """ Function to get grid expantion costs form etrago Parameters @@ -132,6 +153,9 @@ def etrago_grid_investment(network): network : Network eTraGo + json_file : :obj:dict + Dictionary of the ``scenario_setting.json`` file + Returns ------- @@ -141,6 +165,14 @@ def etrago_grid_investment(network): - add new release of etrago 0.7 """ + # check settings for extendable + if 'network' not in ego.json_file['eTraGo']['extendable']: + print("The optimizition was not using parameter 'extendable': network") + print("No grid expantion costs form etrago") + + # capital_cost + # check if extendable == true + pass From e8034b6890dc58fa4ff08e4838867e7c75017229 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 14:22:32 +0200 Subject: [PATCH 160/314] update file --- ego/tools/io.py | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 6a4d2397..9bfcd59f 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -78,10 +78,10 @@ class egoBasic(object): Network container of eTraGo based on PyPSA eDisGo : :pandas:`pandas.Dataframe` of PyPSA Network container of eDisGo based on PyPSA - json_file : dict - Dict of the scenario_setting.json file - session : sqlalchemy - Database session for the oedb connection. + json_file : :obj:dict + Dictionary of the ``scenario_setting.json`` file + session : :sqlalchemy:`sqlalchemy.orm.session.Session` + SQLAlchemy session to the OEDB """ @@ -310,8 +310,8 @@ def geolocation_buses(network, session): ---------- network : Network eTraGo Network - session : sqlalchemy - session to oedb + session : :sqlalchemy:`sqlalchemy.orm.session.Session` + SQLAlchemy session to the OEDB ToDo ---- @@ -370,7 +370,7 @@ def geolocation_buses(network, session): return network -def results_to_excel(results): +def results_to_excel(ego): """ Wirte results to excel @@ -381,10 +381,10 @@ def results_to_excel(results): writer = pd.ExcelWriter('open_ego_results.xlsx', engine='xlsxwriter') # write results of installed Capacity by fuels - results.total.to_excel(writer, index=False, sheet_name='Total Calculation') + ego.total.to_excel(writer, index=False, sheet_name='Total Calculation') # write orgininal data in second sheet - results.to_excel(writer, index=True, sheet_name='Results by carriers') + ego.to_excel(writer, index=True, sheet_name='Results by carriers') # add plots # Close the Pandas Excel writer and output the Excel file. @@ -398,8 +398,8 @@ def etrago_from_oedb(session, args): Parameters ---------- - session (obj): - sqlalchemy session to the OEDB + session : :sqlalchemy:`sqlalchemy.orm.session.Session` + SQLAlchemy session to the OEDB args (dict): args from eGo scenario_setting.json @@ -414,7 +414,7 @@ def etrago_from_oedb(session, args): # modules from model_draft from egoio.db_tables.model_draft import EgoGridPfHvSource as Source,\ EgoGridPfHvTempResolution as TempResolution - from etrago.tools.io import loadcfg + from etrago.tools.io import load_config_file from importlib import import_module import pypsa import re @@ -438,6 +438,18 @@ def map_ormclass(name): def dataframe_results(name, session, result_id, ormclass): """ Function to get pandas DataFrames by the result_id + + + + Parameters + ---------- + session : :sqlalchemy:`sqlalchemy.orm.session.Session` + SQLAlchemy session to the OEDB + + + + + """ query = session.query(ormclass).filter(ormclass.result_id == result_id) @@ -458,6 +470,11 @@ def series_results(name, column, session, meta_args, result_id, ormclass): """ Function to get Time Series as pandas DataFrames by the result_id + Parameters + ---------- + session : :sqlalchemy:`sqlalchemy.orm.session.Session` + SQLAlchemy session to the OEDB + ToDo ---- - check index of bus_t and soon is wrong! @@ -495,7 +512,7 @@ def series_results(name, column, session, meta_args, result_id, ormclass): # create config for results path = os.getcwd() # add meta_args with args of results - config = loadcfg(path+'/tools/config.json')['results'] + config = load_config_file(path+'/tools/config.json')['results'] # map and Database settings of etrago_from_oedb() _prefix = 'EgoGridPfHvResult' From cc8ec8c17d6c93678f9d602bcc4d13fcfb71193b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 14:22:54 +0200 Subject: [PATCH 161/314] update file --- ego/tools/utilities.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index 2dc9ed8a..24c9b61d 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -45,7 +45,10 @@ def define_logging(log_name='ego.log'): ego_logger : :class:`logging.basicConfig`. Set up ``ego_logger`` object of package ``logging`` """ + # ToDo: Logger should be set up more specific + # add pypsa and other logger INFO to ego.log + logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) From 8bd4431f85fbcaac246f1850a370b3617ac67286 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 14:23:53 +0200 Subject: [PATCH 162/314] add extantion and new settings --- doc/conf.py | 2 ++ ego/scenario_setting.json | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 763e37dd..9092938d 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -415,6 +415,8 @@ def __getattr__(cls, name): 'edisgo': ('http://edisgo.readthedocs.io/en/dev',None), 'ding0': ('https://dingo.readthedocs.io/en/dev',None), 'pypsa': ('https://pypsa.org/doc/',None), + 'sqlalchemy': ('https://docs.sqlalchemy.org/en/latest/', + None), } # Numbered figures diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 4ced8a1c..533e8c02 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -3,15 +3,15 @@ "eTraGo": true, "eDisGo": false, "db": "oedb", - "result_id": null, + "result_id": 22, "recover": false, "gridversion": "v0.4.2" }, "eTraGo": { "method": "lopf", "pf_post_lopf": false, - "start_snapshot": 1, - "end_snapshot" : 2, + "start_snapshot": 2952, + "end_snapshot" : 2966, "solver": "gurobi", "solver_options":{}, "scn_name": "NEP 2035", @@ -21,11 +21,11 @@ "lpfile": false, "results": false, "export": false, - "extendable": "['storages']", + "extendable": "['network', 'storages']", "generator_noise": false, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": 20, + "network_clustering_kmeans": 100, "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, From 13981ebe22043ec1022dab41074544df6c722429 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 14:29:30 +0200 Subject: [PATCH 163/314] update file --- ego/tools/io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 9bfcd59f..d6048f16 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -72,7 +72,7 @@ class egoBasic(object): Path to ``scenario_setting.json`` file. - Results + Returns ------- eTraGo : :pandas:`pandas.Dataframe` of PyPSA Network container of eTraGo based on PyPSA From 275c4b747d88e2efd0c572851f4a4917ceb67eab Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 17:08:40 +0200 Subject: [PATCH 164/314] add grid cost function --- ego/tools/economics.py | 35 +++++++++++++++++++++++++++++++---- ego/tools/io.py | 2 ++ ego/tools/utilities.py | 10 +++++----- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index ef36eb98..2c05e605 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -33,6 +33,7 @@ if not 'READTHEDOCS' in os.environ: import pandas as pd import numpy as np + from tools.utilities import get_time_steps __copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ "Flensburg, Centre for Sustainable Energy Systems" @@ -166,14 +167,40 @@ def etrago_grid_investment(network, json_file): """ # check settings for extendable - if 'network' not in ego.json_file['eTraGo']['extendable']: + if 'network' not in json_file['eTraGo']['extendable']: print("The optimizition was not using parameter 'extendable': network") print("No grid expantion costs form etrago") - # capital_cost - # check if extendable == true + if 'network' in json_file['eTraGo']['extendable']: - pass + lines = network.lines[['v_nom', 'capital_cost', 's_nom', + 's_nom_min', 's_nom_opt']] + + lines['s_nom_expansion'] = lines.s_nom_opt.subtract( + lines.s_nom, axis='index') + lines['grid_costs'] = lines.s_nom_expansion.multiply( + lines.capital_cost, axis='index') + lines['number_of_expansion'] = lines.s_nom_expansion > 0.0 + lines['time_step'] = get_time_steps(json_file) + + # print(get_time_steps(json_file)) + + #network.lines[['v_nom','capital_cost','s_nom', 's_nom_min','s_nom_opt']] + + # eTraGo Function: + # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 + # Definition https://pypsa.org/doc/components.html#line + + # capital_cost + # s_nom_extendable + # check if extendable == true + + return lines[['v_nom', 'number_of_expansion', 's_nom_expansion', + 'grid_costs']].groupby('v_nom').sum() + + # ToDo: add .agg({'number_of_expansion':lambda x: x.count(), + # 's_nom_expansion': np.sum, + # 'grid_costs': np.sum}) <- time_step def edisgo_grid_investment(network): diff --git a/ego/tools/io.py b/ego/tools/io.py index d6048f16..82992195 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -160,6 +160,8 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago_network) self.etrago.generator = create_etrago_results(self.etrago_network, self.scn_name) + self.etrago.grid_costs = etrago_grid_investment(self.etrago_network, + self.json_file) # add functions direct # self.etrago_network.etrago_line_loading = etrago_line_loading diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index 24c9b61d..767bac62 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -122,13 +122,13 @@ def get_scenario_setting(json_file='scenario_setting.json'): return scn_set -def get_time_steps(scn_set): +def get_time_steps(json_file): """ Get time step of calculation by scenario settings. Parameters ---------- - scn_set : dict - dict of ``scenario_setting.json`` + json_file : :obj:dict + Dictionary of the ``scenario_setting.json`` file Returns ------- @@ -136,8 +136,8 @@ def get_time_steps(scn_set): Number of timesteps of the calculation. """ - end = args['eTraGo'].get('end_snapshot') - start = args['eTraGo'].get('start_snapshot') + end = json_file['eTraGo'].get('end_snapshot') + start = json_file['eTraGo'].get('start_snapshot') time_step = end - start return time_step From e7009841eb5858fbb0ee8d98678a26717f4074c0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 17:11:45 +0200 Subject: [PATCH 165/314] add docu Example --- ego/tools/economics.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 2c05e605..695adb8b 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -160,10 +160,24 @@ def etrago_grid_investment(network, json_file): Returns ------- + lines: :pandas:`pandas.Dataframe` + Dataframe with ``number_of_expansion``, ``s_nom_expansion`` and + ``grid_costs`` per calculated time steps + + + Example + ------- + .. code-block:: python + ego = eGo(jsonpath='scenario_setting.json' + ego.etrago.grid_costs + + +-----+---------------------+----------------+-----------+ + |v_nom| number_of_expansion | s_nom_expansion| grid_costs| + +=====+=====================+================+===========+ + | 380 | 27.0 | 12678.47943 |31514.1305 | + +-----+---------------------+----------------+-----------+ + - ToDo - ---- - - add new release of etrago 0.7 """ # check settings for extendable From 4b8b664f171e4c029ccc99857fbee2caf52fa5d8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 17:15:31 +0200 Subject: [PATCH 166/314] update docu --- ego/tools/economics.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 695adb8b..bf8d9ddd 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -167,9 +167,11 @@ def etrago_grid_investment(network, json_file): Example ------- - .. code-block:: python - ego = eGo(jsonpath='scenario_setting.json' - ego.etrago.grid_costs + + .. code-block:: python + + ego = eGo(jsonpath='scenario_setting.json' + ego.etrago.grid_costs +-----+---------------------+----------------+-----------+ |v_nom| number_of_expansion | s_nom_expansion| grid_costs| From becb2edd2b438fd8d3c7e13677b977f0aa8eb5eb Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 17:18:34 +0200 Subject: [PATCH 167/314] update docu --- ego/tools/economics.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index bf8d9ddd..32526175 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -169,9 +169,8 @@ def etrago_grid_investment(network, json_file): ------- .. code-block:: python - - ego = eGo(jsonpath='scenario_setting.json' - ego.etrago.grid_costs + ego = eGo(jsonpath='scenario_setting.json' + ego.etrago.grid_costs +-----+---------------------+----------------+-----------+ |v_nom| number_of_expansion | s_nom_expansion| grid_costs| From 949a3d68b01534af172bdd9a05cb0d55c6426e31 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 10 Jul 2018 17:23:15 +0200 Subject: [PATCH 168/314] update documentation --- ego/tools/economics.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 32526175..10f043a7 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -169,8 +169,9 @@ def etrago_grid_investment(network, json_file): ------- .. code-block:: python - ego = eGo(jsonpath='scenario_setting.json' - ego.etrago.grid_costs + + ego = eGo(jsonpath='scenario_setting.json' + ego.etrago.grid_costs +-----+---------------------+----------------+-----------+ |v_nom| number_of_expansion | s_nom_expansion| grid_costs| From 432a8e52fb57e90eaa94fffa941aef738eddee45 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 11 Jul 2018 13:50:05 +0200 Subject: [PATCH 169/314] update file --- ego/tools/economics.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 10f043a7..3462ed52 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -178,6 +178,8 @@ def etrago_grid_investment(network, json_file): +=====+=====================+================+===========+ | 380 | 27.0 | 12678.47943 |31514.1305 | +-----+---------------------+----------------+-----------+ + | 220 | 0.0 | 0.0 | 0.0 | + +-----+---------------------+----------------+-----------+ """ @@ -185,7 +187,7 @@ def etrago_grid_investment(network, json_file): # check settings for extendable if 'network' not in json_file['eTraGo']['extendable']: print("The optimizition was not using parameter 'extendable': network") - print("No grid expantion costs form etrago") + print("No grid expantion costs from etrago") if 'network' in json_file['eTraGo']['extendable']: @@ -211,12 +213,13 @@ def etrago_grid_investment(network, json_file): # s_nom_extendable # check if extendable == true - return lines[['v_nom', 'number_of_expansion', 's_nom_expansion', - 'grid_costs']].groupby('v_nom').sum() + return lines[['v_nom', 'number_of_expansion', 's_nom_expansion', + 'grid_costs']].groupby('v_nom').sum() # ToDo: add .agg({'number_of_expansion':lambda x: x.count(), # 's_nom_expansion': np.sum, # 'grid_costs': np.sum}) <- time_step + pass def edisgo_grid_investment(network): From dc8ef28f6e779f9585e1d02719398d5d460ca642 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 11 Jul 2018 13:50:32 +0200 Subject: [PATCH 170/314] fixed etrago_from_oedb function --- ego/tools/io.py | 98 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 82992195..0bff7acc 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -146,6 +146,30 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago_network = None + if self.json_file['global']['recover'] is True: + + # Delete arguments from scenario_setting + logger.info('Remove given eTraGo settings from scenario_setting') + + try: + self.json_file['global']['eTraGo'] = False + + for i in self.json_file['eTraGo'].keys(): + + self.json_file['eTraGo'][i] = 'removed by recover' + + # ToDo add scenario_setting for results + self.json_file['eTraGo']['db'] = self.json_file['global']['db'] + logger.info( + 'Add `eTraGo` scenario_setting from oedb result') + # To do .... + + except KeyError: + pass + + logger.info('Create eTraGo network from oedb result') + self.etrago_network = etrago_from_oedb(self.session, self.json_file) + # create eTraGo NetworkScenario network if self.json_file['global']['eTraGo'] is True: logger.info('Create eTraGo network') @@ -394,7 +418,7 @@ def results_to_excel(ego): # buses -def etrago_from_oedb(session, args): +def etrago_from_oedb(session, json_file): """ Function with import eTraGo results for the Database. @@ -402,16 +426,19 @@ def etrago_from_oedb(session, args): ---------- session : :sqlalchemy:`sqlalchemy.orm.session.Session` SQLAlchemy session to the OEDB + json_file : :obj:dict + Dictionary of the ``scenario_setting.json`` file - args (dict): - args from eGo scenario_setting.json + Returns + ------- + network : ToDo ---- add Mapping for grid schema make it more generic -> class? """ - result_id = args['global']['result_id'] + result_id = json_file['global']['result_id'] # modules from model_draft from egoio.db_tables.model_draft import EgoGridPfHvSource as Source,\ @@ -421,8 +448,7 @@ def etrago_from_oedb(session, args): import pypsa import re import logging - logging.basicConfig(level=logging.INFO) - logger = logging.getLogger(__name__) + logger = logging.getLogger('ego') # functions def map_ormclass(name): @@ -441,17 +467,10 @@ def dataframe_results(name, session, result_id, ormclass): """ Function to get pandas DataFrames by the result_id - - Parameters ---------- session : :sqlalchemy:`sqlalchemy.orm.session.Session` SQLAlchemy session to the OEDB - - - - - """ query = session.query(ormclass).filter(ormclass.result_id == result_id) @@ -511,6 +530,47 @@ def series_results(name, column, session, meta_args, result_id, ormclass): return df + def recover_resultsettings(session, json_file, orm_meta): + """ Recover scenario_setting from database + """ + + # check result_id + result_id_in = session.query( + orm_meta.result_id).filter(orm_meta. + result_id == result_id).all() + if result_id_in: + logger.info('Choosen result_id %s found in DB', result_id) + else: + logger.info('Error: result_id not found in DB') + + # get meta data as json_file + meta = session.query(orm_meta.result_id, orm_meta.scn_name, orm_meta.calc_date, + orm_meta.user_name, orm_meta.method, orm_meta.start_snapshot, + orm_meta.end_snapshot, orm_meta.solver, orm_meta.settings + ).filter(orm_meta.result_id == result_id) + + meta_df = pd.read_sql( + meta.statement, meta.session.bind, index_col='result_id') + + # update json_file with main data by result_id + json_file['eTraGo']['scn_name'] = meta_df.scn_name[result_id] + json_file['eTraGo']['method'] = meta_df.method[result_id] + json_file['eTraGo']['start_snapshot'] = meta_df.start_snapshot[result_id] + json_file['eTraGo']['end_snapshot'] = meta_df.end_snapshot[result_id] + json_file['eTraGo']['solver'] = meta_df.solver[result_id] + + # update json_file with specific data by result_id + meta_set = dict(meta_df.settings[result_id]) + + for key in json_file['eTraGo'].keys(): + + try: + json_file['eTraGo'][key] = meta_set[key] + except KeyError: + pass + + return json_file + # create config for results path = os.getcwd() # add meta_args with args of results @@ -526,14 +586,15 @@ def series_results(name, column, session, meta_args, result_id, ormclass): _mapped = {} # get metadata - version = args['global']['gridversion'] + #version = json_file['global']['gridversion'] orm_meta = getattr(_pkg, _prefix + 'Meta') # check result_id - result_id_in = session.query(orm_meta.result_id).filter(orm_meta. - result_id == result_id).all() + result_id_in = session.query( + orm_meta.result_id).filter(orm_meta. + result_id == result_id).all() if result_id_in: logger.info('Choosen result_id %s found in DB', result_id) else: @@ -569,6 +630,11 @@ def series_results(name, column, session, meta_args, result_id, ormclass): 1: meta_args['end_snapshot']] meta_args['temp_id'] = tr.temp_id + print(meta_args) + print('und das neue') + + meta_test = recover_resultsettings(session, json_file, orm_meta) + print(meta_test) # create df for PyPSA network From e5cfd665b9eec83415a219ec1efb09d9216cea7f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 11 Jul 2018 13:51:12 +0200 Subject: [PATCH 171/314] add import oedb setting --- ego/scenario_setting.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 533e8c02..94a67ef6 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -3,8 +3,8 @@ "eTraGo": true, "eDisGo": false, "db": "oedb", - "result_id": 22, - "recover": false, + "result_id": 26, + "recover": true, "gridversion": "v0.4.2" }, "eTraGo": { From 1dce289c41184b19e79bb03177298163bcacc5bc Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 11 Jul 2018 15:25:53 +0200 Subject: [PATCH 172/314] update file --- ego/tools/economics.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 3462ed52..930830ed 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -157,21 +157,20 @@ def etrago_grid_investment(network, json_file): json_file : :obj:dict Dictionary of the ``scenario_setting.json`` file - Returns ------- lines: :pandas:`pandas.Dataframe` Dataframe with ``number_of_expansion``, ``s_nom_expansion`` and ``grid_costs`` per calculated time steps - Example ------- .. code-block:: python - ego = eGo(jsonpath='scenario_setting.json' - ego.etrago.grid_costs + >>> from ego.tools.io import eGo + >>> ego = eGo(jsonpath='scenario_setting.json' + >>> ego.etrago.grid_costs +-----+---------------------+----------------+-----------+ |v_nom| number_of_expansion | s_nom_expansion| grid_costs| @@ -180,8 +179,6 @@ def etrago_grid_investment(network, json_file): +-----+---------------------+----------------+-----------+ | 220 | 0.0 | 0.0 | 0.0 | +-----+---------------------+----------------+-----------+ - - """ # check settings for extendable From dfa72750199f0cb891bec61a55a40071b5e6f707 Mon Sep 17 00:00:00 2001 From: maltesc Date: Wed, 11 Jul 2018 18:42:35 +0200 Subject: [PATCH 173/314] edisgo integration first steps --- ego/scenario_setting.json | 6 +- ego/tools/edisgo_integration.py | 142 +++++++++++----- ego/tools/specs.py | 281 +++++++++++++++++++++++++------- 3 files changed, 322 insertions(+), 107 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index e2d6212e..ba760fae 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -21,7 +21,7 @@ "lpfile": false, "results": false, "export": false, - "extendable": "['storages']", + "extendable": null, "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, @@ -32,9 +32,9 @@ "parallelisation": false, "skip_snapshots": false, "line_grouping": false, - "branch_capacity_factor": 1, + "branch_capacity_factor": 0.8, "load_shedding": true, - "comments": null + "comments": "eDisGo integration" }, "eDisGo": { "specs": true, diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index e7257c38..aa7ec25c 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -15,11 +15,18 @@ ## Project Packages from egoio.db_tables import model_draft, grid from egoio.tools import db -from edisgo.grid.network import Results +from edisgo.grid.network import Results, TimeSeriesControl from edisgo.tools.edisgo_run import ( run_edisgo_basic ) -from ego.tools.specs import (get_etragospecs_direct) +from ego.tools.specs import ( + get_etragospecs_direct, +# get_feedin_fluctuating, +# get_curtailment + ) +from ego.tools.mv_cluster import ( + analyze_attributes, + cluster_mv_grids) ## Other Packages import os @@ -32,7 +39,7 @@ class EDisGoNetworks: """ - Represents multiple eDisGo networks + Represents multiple eDisGo networks. """ @@ -52,10 +59,10 @@ def __init__(self, **kwargs): if self._scn_name == 'Status Quo': self._generator_scn = None - if self._scn_name == 'NEP 2035': + elif self._scn_name == 'NEP 2035': self._generator_scn = 'nep2035' elif self._scn_name == 'eGo100': - raise NotImplementedError + self._generator_scn = 'ego100' if self._grid_version is not None: self._versioned = True @@ -64,6 +71,27 @@ def __init__(self, **kwargs): self._etrago_network = kwargs.get('etrago_network', None) + + def analyze_cluster_attributes(self): + """ + Analyses the attributes wind and solar capacity and farthest node + for clustering. + """ + analyze_attributes(self._ding0_files) + + def cluster_mv_grids(self, no_grids): + """ + Clusters the MV grids based on the attributes + + """ + attributes_path = self._ding0_files + '/attributes.csv' + + if not os.path.isfile(attributes_path): + logger.info('Attributes file is missing') + logger.info('Attributes will be calculated') + self.analyze_cluster_attributes() + + self._cluster = cluster_mv_grids(self._ding0_files, no_grids) def check_available_mv_grids(self): @@ -80,10 +108,11 @@ def check_available_mv_grids(self): def run_edisgo(self, mv_grid_id): """ - Runs eDisGo with the desired settings + Runs eDisGo with the desired settings. """ + logger.info('Calculating interface values') bus_id = self.get_bus_id_from_mv_grid(mv_grid_id) specs = get_etragospecs_direct( @@ -93,38 +122,51 @@ def run_edisgo(self, mv_grid_id): self._scn_name) return specs - -# ding0_filepath = ( -# self._ding0_files -# + '/ding0_grids__' -# + str(mv_grid_id) -# + '.pkl') -# -# if not os.path.isfile(ding0_filepath): -# msg = 'Not MV grid file for MV grid ID: ' + str(mv_grid_id) -# logger.error(msg) -# raise Exception(msg) -# -# - -# ### Base case with no generator import (initial reinforcement) -# edisgo_grid, \ -# costs_before_geno_import, \ -# grid_issues_before_geno_import = run_edisgo_basic( -# ding0_filepath=ding0_filepath, -# generator_scenario=None, -# analysis='worst-case') -# -# ### Second run for corresponding scenario -# edisgo_grid.network.results = Results() -# edisgo_grid.network.pypsa = None -# -# if self._generator_scn: -# edisgo_grid.import_generators( -# generator_scenario=self._generator_scn) - + + ding0_filepath = ( + self._ding0_files + + '/ding0_grids__' + + str(mv_grid_id) + + '.pkl') + + if not os.path.isfile(ding0_filepath): + msg = 'Not MV grid file for MV grid ID: ' + str(mv_grid_id) + logger.error(msg) + raise Exception(msg) + + logger.info('Initial MV grid reinforcement (starting grid)') + edisgo_grid, \ + costs_before_geno_import, \ + grid_issues_before_geno_import = run_edisgo_basic( + ding0_filepath=ding0_filepath, + generator_scenario=None, + analysis='worst-case') + + logger.info('eTraGo feed-in case') + edisgo_grid.network.results = Results() + edisgo_grid.network.pypsa = None + + if self._generator_scn: + edisgo_grid.import_generators( + generator_scenario=self._generator_scn) + + edisgo_grid.network.timeseries = TimeSeriesControl( + timeseries_generation_fluctuating=specs['potential_abs'] , + timeseries_generation_dispatchable=specs['conv_dispatch_abs'], + timeseries_load='demandlib', + weather_cell_ids=edisgo_grid.network.mv_grid._weather_cells, + config_data=edisgo_grid.network.config, + timeindex=specs['conv_dispatch_abs'].index).timeseries + + edisgo_grid.curtail(curtailment_methodology='curtail_all', + timeseries_curtailment=specs['curtailment_abs']) + edisgo_grid.network.pypsa = None + + edisgo_grid.analyze() + + ## Helpful tools def get_mv_grid_from_bus_id(self, bus_id): @@ -187,21 +229,37 @@ def get_bus_id_from_mv_grid(self, subst_id): def get_hvmv_translation(self): raise NotImplementedError - - # Hier clustering usw. - - - + + test = EDisGoNetworks( json_file=ego.json_file, etrago_network=ego.etrago_network) +specs = test.run_edisgo(mv_grid_id=1729) + +#specs['dispatch'] +#specs['dispatch_abs'] +#specs['potential'] +#specs['potential_abs'] +#specs['curtailment'] +#specs['curtailment_abs'] +# +#specs['conv_dispatch'] +#specs['conv_dispatch_abs'] + +#specs['ren_feedin'] +#specs['ren_curtailment'] +#specs['ren_curtailment_abs'] + + + + # #test._edisgo_args -ed = test.run_edisgo(mv_grid_id=1729) +#ed = test.run_edisgo(mv_grid_id=1729) # #ed.network.results.equipment_changes diff --git a/ego/tools/specs.py b/ego/tools/specs.py index b1fd08b6..402c6145 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -28,7 +28,7 @@ from sqlalchemy import distinct # This gives me the specific ORM classes. from egoio.db_tables import model_draft - from edisgo.grid.network import ETraGoSpecs +# from edisgo.grid.network import ETraGoSpecs import logging logger = logging.getLogger('ego') @@ -410,18 +410,20 @@ def get_etragospecs_direct(session, """ - print("\nSpecs Direct") specs_meta_data = {} performance = {} specs_meta_data.update({'TG Bus ID': bus_id}) # ormclass_result_meta = model_draft.__getattribute__('EgoGridPfHvResultMeta') - ormclass_aggr_w = model_draft.__getattribute__( - 'ego_supply_aggr_weather_mview') + ormclass_gen_single = model_draft.__getattribute__('EgoSupplyPfGeneratorSingle') +# ormclass_aggr_w = model_draft.t_ego_supply_aggr_weather_mview + +# __getattribute__( +# 'ego_supply_aggr_weather_mview') logger.warning('Weather table taken from model_draft') - ormclass_source = model_draft.__getattribute__('EgoGridPfHvSource') - logger.warning('Source table taken from model_draft') +# ormclass_source = model_draft.__getattribute__('EgoGridPfHvSource') +# logger.warning('Source table taken from model_draft') snap_idx = etrago_network.snapshots @@ -444,7 +446,7 @@ def get_etragospecs_direct(session, # Generators t0 = time.perf_counter() - weather_dpdnt = ['wind', 'solar'] + weather_dpdnt = ['wind', 'solar', 'wind_onshore', 'wind_offshore'] # DF procesing all_gens_df = etrago_network.generators[etrago_network.generators['bus'] == str(bus_id)] @@ -452,20 +454,33 @@ def get_etragospecs_direct(session, all_gens_df = all_gens_df.rename(columns={'index': 'generator_id'}) all_gens_df = all_gens_df[['generator_id', 'p_nom', 'p_nom_opt', 'carrier']] - names = [] + all_gens_df = all_gens_df.rename(columns={"carrier": "name"}) + + all_gens_df = all_gens_df[all_gens_df['name'] != 'wind_offshore'] + logger.warning('Wind offshore is disregarded in the interface') + for index, row in all_gens_df.iterrows(): - carrier = row['carrier'] - name = session.query( - ormclass_source.name - ).filter( - ormclass_source.source_id == carrier - ).scalar( - ) - - names.append(name) + name = row['name'] + if name == 'wind_onshore': + all_gens_df.at[index, 'name'] = 'wind' + logger.warning('wind onshore is renamed to wind') + +# print(all_gens_df) +# names = [] +# for index, row in all_gens_df.iterrows(): +# carrier = row['carrier'] +# name = session.query( +# ormclass_source.name +# ).filter( +# ormclass_source.source_id == carrier +# ).scalar( +# ) +# +# names.append(name) - all_gens_df['name'] = names - all_gens_df = all_gens_df.drop(['carrier'], axis=1) +# all_gens_df['name'] = names + +# all_gens_df = all_gens_df.drop(['carrier'], axis=1) # Conventionals t1 = time.perf_counter() @@ -477,6 +492,9 @@ def get_etragospecs_direct(session, conv_dsptch_norm = pd.DataFrame(0.0, index=snap_idx, columns=list(set(conv_df['name']))) + conv_dsptch_abs = pd.DataFrame(0.0, + index=snap_idx, + columns=list(set(conv_df['name']))) for index, row in conv_df.iterrows(): generator_id = row['generator_id'] @@ -484,6 +502,7 @@ def get_etragospecs_direct(session, p = etrago_network.generators_t.p[str(generator_id)] p_norm = p / conv_cap[source]['p_nom'] conv_dsptch_norm[source] = conv_dsptch_norm[source] + p_norm + conv_dsptch_abs[source] = conv_dsptch_abs[source] + p # Renewables t2 = time.perf_counter() @@ -491,22 +510,28 @@ def get_etragospecs_direct(session, # Capacities ren_df = all_gens_df[all_gens_df.name.isin(weather_dpdnt)] - w_ids = [] + + + +# w_ids = [] for index, row in ren_df.iterrows(): aggr_id = row['generator_id'] w_id = session.query( - ormclass_aggr_w.c.w_id + ormclass_gen_single.w_id ).filter( - ormclass_aggr_w.c.aggr_id == aggr_id, - ormclass_aggr_w.c.scn_name == scn_name - ).scalar( + ormclass_gen_single.aggr_id == aggr_id, + ormclass_gen_single.scn_name == scn_name + ).limit(1).scalar( ) - w_ids.append(w_id) + ren_df.at[index, 'w_id'] = w_id + +# w_ids.append(w_id) - ren_df = ren_df.assign(w_id=pd.Series(w_ids, index=ren_df.index)) - # This should be unnecessary (and I think it isnt) +# ren_df = ren_df.assign(w_id=pd.Series(w_ids, index=ren_df.index)) +# # This should be unnecessary (and I think it isnt) ren_df.dropna(inplace=True) +# print(ren_df) aggr_gens = ren_df.groupby([ 'name', @@ -516,14 +541,29 @@ def get_etragospecs_direct(session, aggr_gens.rename(columns={'p_nom': 'p_nom_aggr'}, inplace=True) aggr_gens['ren_id'] = aggr_gens.index + +# print(aggr_gens) ### Dispatch and Curteilment + potential = pd.DataFrame(0.0, + index=snap_idx, + columns=aggr_gens['ren_id']) dispatch = pd.DataFrame(0.0, index=snap_idx, columns=aggr_gens['ren_id']) curtailment = pd.DataFrame(0.0, index=snap_idx, columns=aggr_gens['ren_id']) + + potential_abs = pd.DataFrame(0.0, + index=snap_idx, + columns=aggr_gens['ren_id']) + dispatch_abs = pd.DataFrame(0.0, + index=snap_idx, + columns=aggr_gens['ren_id']) + curtailment_abs = pd.DataFrame(0.0, + index=snap_idx, + columns=aggr_gens['ren_id']) for index, row in ren_df.iterrows(): gen_id = row['generator_id'] @@ -535,19 +575,69 @@ def get_etragospecs_direct(session, p_nom_aggr = float( aggr_gens[aggr_gens['ren_id'] == ren_id]['p_nom_aggr']) - p_nom = float(ren_df[ren_df['generator_id'] == gen_id]['p_nom']) +# p_nom = float(ren_df[ren_df['generator_id'] == gen_id]['p_nom']) + p_nom = row['p_nom'] p_series = etrago_network.generators_t.p[str(gen_id)] p_norm_tot_series = p_series / p_nom_aggr p_max_pu_series = etrago_network.generators_t.p_max_pu[str(gen_id)] + p_max_series = p_max_pu_series * p_nom p_max_norm_tot_series = p_max_pu_series * p_nom / p_nom_aggr + p_curt_tot_series = p_max_series - p_series p_curt_norm_tot_series = p_max_norm_tot_series - p_norm_tot_series dispatch[ren_id] = dispatch[ren_id] + p_norm_tot_series curtailment[ren_id] = curtailment[ren_id] + p_curt_norm_tot_series - + + potential_abs[ren_id] = potential_abs[ren_id] + p_max_series + dispatch_abs[ren_id] = dispatch_abs[ren_id] + p_series + curtailment_abs[ren_id] = curtailment_abs[ren_id] + p_curt_tot_series + + + potential = dispatch + curtailment + + new_columns = [ + (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], + aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) + for col in potential.columns] + potential.columns = pd.MultiIndex.from_tuples(new_columns) + + new_columns = [ + (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], + aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) + for col in dispatch.columns] + dispatch.columns = pd.MultiIndex.from_tuples(new_columns) + + new_columns = [ + (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], + aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) + for col in curtailment.columns] + curtailment.columns = pd.MultiIndex.from_tuples(new_columns) + + new_columns = [ + (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], + aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) + for col in potential_abs.columns] + potential_abs.columns = pd.MultiIndex.from_tuples(new_columns) + + new_columns = [ + (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], + aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) + for col in dispatch_abs.columns] + dispatch_abs.columns = pd.MultiIndex.from_tuples(new_columns) + + new_columns = [ + (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], + aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) + for col in curtailment_abs.columns] + curtailment_abs.columns = pd.MultiIndex.from_tuples(new_columns) + + potential_abs = potential_abs * 1000 + dispatch_abs = dispatch_abs * 1000 + curtailment_abs = curtailment_abs * 1000 + # Storage t3 = time.perf_counter() performance.update({'Renewable Dispatch and Curt.': t3-t2}) @@ -562,21 +652,25 @@ def get_etragospecs_direct(session, 'max_hours', 'carrier']] - names = [] - for index, row in stor_df.iterrows(): - carrier = row['carrier'] - name = session.query( - ormclass_source.name - ).filter( - ormclass_source.source_id == carrier - ).scalar( - ) - - names.append(name) - - stor_df = stor_df.assign(name=pd.Series(names, index=stor_df.index)) - stor_df = stor_df.drop(['carrier'], axis=1) +# print(stor_df) + +# names = [] +# for index, row in stor_df.iterrows(): +# carrier = row['carrier'] +# name = session.query( +# ormclass_source.name +# ).filter( +# ormclass_source.source_id == carrier +# ).scalar( +# ) +# +# names.append(name) +# +# stor_df = stor_df.assign(name=pd.Series(names, index=stor_df.index)) +# stor_df = stor_df.drop(['carrier'], axis=1) + stor_df = stor_df.rename(columns={"carrier": "name"}) + stor_df['capacity_MWh'] = stor_df['p_nom_opt'] * stor_df['max_hours'] count_bat = 0 @@ -607,29 +701,32 @@ def get_etragospecs_direct(session, t4 = time.perf_counter() performance.update({'Storage Data Processing and Dispatch': t4-t3}) - specs = ETraGoSpecs(battery_capacity=battery_capacity, - battery_active_power=battery_active_power, - - conv_dispatch=conv_dsptch_norm, - - renewables=aggr_gens, - ren_dispatch=dispatch, - ren_curtailment=curtailment) + specs = { +# 'battery_capacity': battery_capacity, +# 'battery_active_power': battery_active_power, + 'conv_dispatch': conv_dsptch_norm, + 'conv_dispatch_abs': conv_dsptch_abs, +# 'renewables': aggr_gens, + 'dispatch': dispatch, + 'dispatch_abs': dispatch_abs, + 'potential': potential, + 'potential_abs': potential_abs, + 'curtailment': curtailment, + 'curtailment_abs': curtailment_abs + } + +# specs = ETraGoSpecs(battery_capacity=battery_capacity, +# battery_active_power=battery_active_power, +# +# conv_dispatch=conv_dsptch_norm, +# +# renewables=aggr_gens, +# ren_dispatch=dispatch, +# ren_curtailment=curtailment) t5 = time.perf_counter() performance.update({'Overall time': t5-t0}) - # print(performance) - -# print("\n Conventional Dispatch (Normalized): \n", -# conv_dsptch_norm, -# "\n\n Renewable Generators: \n", -# aggr_gens, -# "\n\n Renewable Dispatch: \n", -# dispatch, -# "\n\n Renewable Curtailment: \n", -# curtailment, "\n\n") -# # for keys,values in performance.items(): # print(keys, ": ", values) @@ -649,3 +746,63 @@ def get_etragospecs_direct(session, # # ToDo Check if subst_id is really the mv grid ID # # Anyway, this should be adapted by Dingo # return subst_id + +#def get_feedin_fluctuating(ren_dispatch, curtailment, renewables): +# +# # get feed-in without curtailment +# if curtailment is not None: +# print(ren_dispatch) +# print(curtailment) +# feedin = ren_dispatch + curtailment +# print(feedin) +# logger.info('Feed-in calculated including curtailment') +# else: +# feedin = ren_dispatch +# # change column names +# new_columns = [ +# (renewables[renewables.ren_id == col].name.iloc[0], +# renewables[renewables.ren_id == col].w_id.iloc[0]) +# for col in feedin.columns] +# feedin.columns = pd.MultiIndex.from_tuples(new_columns) +# # aggregate wind and solar time series until generators get a weather +# # ID +# print(feedin) +# return feedin + + +#def get_curtailment(edisgo_grid, curtailment, renewables): +# +# # get installed capacities of wind and solar generators +# # ToDo: Differentiate by weather cell ID once generators have one +# gens = list(edisgo_grid.network.mv_grid.graph.nodes_by_attribute( +# 'generator')) +# for lv_grid in edisgo_grid.network.mv_grid.lv_grids: +# gens.extend(list(lv_grid.graph.nodes_by_attribute('generator'))) +# dict_capacities = {'solar': 0, 'wind': 0} +# for gen in gens: +# if gen.type in ['solar', 'wind']: +# dict_capacities[gen.type] = ( +# dict_capacities[gen.type] +# + gen.nominal_capacity) +# print(dict_capacities) +# +# # change column names of curtailment DataFrame to +# new_columns = [ +# (renewables[renewables.ren_id == col].name.iloc[0], +# renewables[renewables.ren_id == col].w_id.iloc[0]) +# for col in curtailment.columns] +# curtailment.columns = pd.MultiIndex.from_tuples(new_columns) +# +# +# return curtailment + +#Hier curtailment noch zusammenfassen!! + +# curtailment = pd.DataFrame(data={'wind': curtailment.wind.sum(axis=1), +# 'solar': curtailment.solar.sum(axis=1)}) +# +# # calculate absolute curtailment +# timeseries_curtailment = curtailment.multiply( +# pd.Series(dict_capacities)) +# +# return timeseries_curtailment \ No newline at end of file From 26b1ef49dde85f77ff6ae049f5f7fbab3367bd28 Mon Sep 17 00:00:00 2001 From: maltesc Date: Wed, 11 Jul 2018 18:57:15 +0200 Subject: [PATCH 174/314] edisgo integration first steps, normalized feedin --- ego/tools/edisgo_integration.py | 47 ++++++++------------------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index aa7ec25c..11d55dc1 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -121,8 +121,6 @@ def run_edisgo(self, mv_grid_id): self._etrago_network, self._scn_name) - return specs - ding0_filepath = ( self._ding0_files + '/ding0_grids__' @@ -151,17 +149,20 @@ def run_edisgo(self, mv_grid_id): edisgo_grid.import_generators( generator_scenario=self._generator_scn) - edisgo_grid.network.timeseries = TimeSeriesControl( - timeseries_generation_fluctuating=specs['potential_abs'] , - timeseries_generation_dispatchable=specs['conv_dispatch_abs'], + edisgo_grid.network.timeseries = TimeSeriesControl( + # Here, I use only normalized values from specs + timeseries_generation_fluctuating=specs['potential'], + timeseries_generation_dispatchable=specs['conv_dispatch'], timeseries_load='demandlib', weather_cell_ids=edisgo_grid.network.mv_grid._weather_cells, config_data=edisgo_grid.network.config, - timeindex=specs['conv_dispatch_abs'].index).timeseries + timeindex=specs['conv_dispatch'].index).timeseries - edisgo_grid.curtail(curtailment_methodology='curtail_all', - timeseries_curtailment=specs['curtailment_abs']) - +# edisgo_grid.curtail(curtailment_methodology='curtail_all', +# # Here, I use absolute values +# timeseries_curtailment=specs['curtailment_abs']) + # Think about the other curtailment functions!!!! + edisgo_grid.network.pypsa = None edisgo_grid.analyze() @@ -238,32 +239,6 @@ def get_hvmv_translation(self): json_file=ego.json_file, etrago_network=ego.etrago_network) -specs = test.run_edisgo(mv_grid_id=1729) - -#specs['dispatch'] -#specs['dispatch_abs'] -#specs['potential'] -#specs['potential_abs'] -#specs['curtailment'] -#specs['curtailment_abs'] -# -#specs['conv_dispatch'] -#specs['conv_dispatch_abs'] - -#specs['ren_feedin'] -#specs['ren_curtailment'] -#specs['ren_curtailment_abs'] - - - +test.run_edisgo(mv_grid_id=1729) -# -#test._edisgo_args -#ed = test.run_edisgo(mv_grid_id=1729) -# -#ed.network.results.equipment_changes -#test._session -#t = test.get_mv_grid_from_bus_id(25214) -#test.get_bus_id_from_mv_grid(168) -#print(t) From 3573cb61ecfddaad4b986cb51006ebc163b7d627 Mon Sep 17 00:00:00 2001 From: maltesc Date: Thu, 12 Jul 2018 09:48:41 +0200 Subject: [PATCH 175/314] adding clustering algorithm --- ego/tools/mv_cluster.py | 285 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 ego/tools/mv_cluster.py diff --git a/ego/tools/mv_cluster.py b/ego/tools/mv_cluster.py new file mode 100644 index 00000000..46ee72c0 --- /dev/null +++ b/ego/tools/mv_cluster.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Thu Apr 19 09:50:36 2018 + +@author: student +""" + +from __future__ import print_function + +import pickle +import os +import pandas as pd + +from sklearn.cluster import KMeans +import numpy as np +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +import matplotlib.cm as cm + +def analyze_attributes(ding0_files): + + base_path = ding0_files + + not_found = [] + tccs = [] # Total Cumulative Capacity of Solar + tccw = [] # Total Cumulative Capacity of Wind + fnlvmv = [] # the Farthest Node in both networks (lv and mv) + MV_id_list = [] # Distrct id list + + for district_number in list(range(1,4000)): # 3608 MVGDs + + # To bypass not found error + try: + pickle_name = 'ding0_grids__{}.pkl'.format(district_number) # To open the pickle files + nd = pickle.load(open(os.path.join(base_path, pickle_name), 'rb')) # assign the data to a variable + print('District no.', district_number, 'found!') + except: + not_found.append(district_number) # append not found network files id to a list + #print('District no.', district_number, 'NOT found') # print not found ids + continue + + MV_id = 0 + MV_id = nd._mv_grid_districts[0].id_db + + mv_cum_solar_MV = 0 # Solar cumulative capacity in MV + mv_cum_wind_MV = 0 # Solar cumulative capacity in MV + + # cumulative capacity of solar and wind in MV + for geno in nd._mv_grid_districts[0].mv_grid.generators(): + if geno.type == 'solar': + mv_cum_solar_MV += geno.capacity + if geno.type == 'wind': + mv_cum_wind_MV += geno.capacity + + lvg = 0 +# lvg_type = [] +# counter_lv = [{}] + mv_cum_solar_LV = 0 + mv_cum_wind_LV = 0 + + # cumulative capacity of solar and wind in LV + for lvgs in nd._mv_grid_districts[0].lv_load_areas(): + for lvgs1 in lvgs.lv_grid_districts(): + lvg += len(list(lvgs1.lv_grid.generators())) # No. of DGs in lv + for deno in lvgs1.lv_grid.generators(): + if deno.type == 'solar': + mv_cum_solar_LV += deno.capacity + if deno.type == 'wind': + mv_cum_wind_LV += deno.capacity + + total_cum_solar = mv_cum_solar_MV + mv_cum_solar_LV # Total solar cumulative capacity in lv and mv + total_cum_wind = mv_cum_wind_MV + mv_cum_wind_LV # Total wind cumulative capacity in lv and mv + + # append to lists + tccs.append(total_cum_solar) + tccw.append(total_cum_wind) + + # The farthest node length from MV substation + from ding0.core.network.stations import LVStationDing0 + + tot_dist = [] + max_length = 0 + max_length_list = [] + max_of_max = 0 + + nd.control_circuit_breakers(mode='open') # make CB open (normal operation case) + root_mv = nd._mv_grid_districts[0].mv_grid.station() # setting the root to measure the path from + # 1st from MV substation to LV station node + for node2 in nd._mv_grid_districts[0].mv_grid._graph.nodes(): # Iteration through nodes + if isinstance(node2, LVStationDing0) and not node2.lv_load_area.is_aggregated: # select only LV station nodes + + length_from_MV_to_LV_station = 0 + # Distance from MV substation to LV station node + length_from_MV_to_LV_station = nd._mv_grid_districts[0].mv_grid.graph_path_length(node_source=node2,node_target=root_mv) / 1000 + # 2nd from LV station node to the longest distance node + + for lvgs in nd._mv_grid_districts[0].lv_load_areas(): # Iteration through lv load areas + for lvgs1 in lvgs.lv_grid_districts(): # Iteration through lv grid districts + # In order to measure the distance between the LV station and the nodes that belong to it and not from other stations + if lvgs1.lv_grid._station == node2: + root_lv = node2 # setting a new root + for node1 in lvgs1.lv_grid._graph.nodes(): # iteration of all nodes in LV grid + + length_from_LV_staion_to_LV_node = 0 + # Distance from LV station to LV nodes + length_from_LV_staion_to_LV_node = lvgs1.lv_grid.graph_path_length(node_source=node1,node_target=root_lv) / 1000 + + length_from_LV_node_to_MV_substation = 0 + # total distances in both grids MV and LV + length_from_LV_node_to_MV_substation = length_from_MV_to_LV_station + length_from_LV_staion_to_LV_node + + tot_dist.append(length_from_LV_node_to_MV_substation) # append the total distance to a list + if any(tot_dist): # to make sure the list is not empty + max_length = max(tot_dist) # to pick up the max length within this grid + max_length_list.append(max_length) # append max lengths of all grids to a list + if any(max_length_list): # to make sure the list is not empty + max_of_max = max(max_length_list) # to pick up max of max + + fnlvmv.append(max_of_max) # append to a new list + MV_id_list.append(MV_id) # append the network id to a new list + + # export results to dataframes + d = {'id': MV_id_list,'Solar_cumulative_capacity': tccs, + 'Wind_cumulative_capacity': tccw, + 'The_Farthest_node': fnlvmv} # assign lists to columns + # not founded networks + are_not_found = {'District_files_that_are_not_found': not_found} + + df = pd.DataFrame(d) # dataframe for results + + df_are_not_found = pd.DataFrame(are_not_found) # dataframe for not found files id + + # Exporting dataframe to CSV files + df.to_csv(base_path + '/' + 'attributes.csv', sep=',') + df_are_not_found.to_csv(base_path + '/' + 'Not_found_grids.csv', sep=',') + + ##3d scatter plotting + #from mpl_toolkits.mplot3d import Axes3D + #import matplotlib.pyplot as plt + # + #fig = plt.figure() + #ax = fig.add_subplot(111, projection='3d') + # + #X = tccs + #Y = tccw + #Z = fnlvmv + # + #ax.scatter(X, Y, Z) + # + #ax.set_xlim(0, max(tccs)/1000) + #ax.set_ylim(0, max(tccw)/1000) + #ax.set_zlim(0, max(fnlvmv)) + # + #ax.set_xlabel('\nSolar cumulative capacity (MW)', linespacing=2) + #ax.set_ylabel('\nWind cumulative capacity (MW)', linespacing=2) + #ax.set_zlabel('\nThe farthest node (km)', linespacing=2) + # + #plt.show() + + +def cluster_mv_grids(ding0_files, no_grids): + + # import CSV data file that exported from Networks_analysis_solar_wind_farthest-node.py and assign it to a data frame + df = pd.read_csv(ding0_files + '/attributes.csv') + + # extract each column to a variable + x = df.Solar_cumulative_capacity # Solar capacity in MV and LV + y = df.Wind_cumulative_capacity # Wind capacity in MV and LV + z = df.The_Farthest_node # The farthest node (the length between HV/MV substation to the farthest node in LV networks) + id_ = df.id # Network id + + # Addressing the max value of each column + max_solar = max(x) + max_wind = max(y) + max_farthest = max(z) + + # Converting data to perunit scale + solar_pu = x / max_solar + wind_pu = y / max_wind + distances_pu = z / max_farthest + + # Converting from vectors to coordinates array + m = [] + for r, s, t in zip(solar_pu, wind_pu, distances_pu): + f = [r, s, t] + m.append(f) + X = np.array(m) + + # Initialize KMeans clustering by Sklearn pkg + no_clusters = no_grids # no. of clusters + + # random state should be given in order to have same results with every run of the script + # it acts as a seed where the algorihm define the starting clustering point, 1808 shows good results + ran_state = 1808 + + # Starting KMeans clustering + kmeans = KMeans(n_clusters=no_clusters,random_state=ran_state) + + # Return a label for each point which indicates to which cluster each point is assigned + cluster_labels = kmeans.fit_predict(X) + + # Centers of clusters + centroids = kmeans.cluster_centers_ + + id_clus_dist = {} + + # Iterate through each point in dataset array X + for i in range(len(X)): + clus = cluster_labels[i] # point's cluster id + cent = centroids[cluster_labels[i]] # Cluster's center coordinates + + # Distance from that point to cluster's center (3d coordinates) + dist = ((X[i][0] - centroids[clus][0]) ** 2 + (X[i][1] - centroids[clus][1]) ** 2 + (X[i][2] - centroids[clus][2]) ** 2) ** (1 / 2) + + # three results are appended to a list (cluster's id, point's (MVGD) id and distance from that point to cluster's center) + #id_clus_dist = [clus, id_[i], dist] + #list_id_clus_dist.append(id_clus_dist) + + # three results are appended to a dictionary (cluster's id, point's (MVGD) id and distance from that point to cluster's center) + id_clus_dist.setdefault(clus, []).append({id_[i]: dist}) + + cluster_id = [] + cluster_points = [] + clus_percentage = [] + closest_point = [] + + #Iterating through the clusters dictionary (key represents cluster's id , value represents another disctionary with network's id and distance of that point to cluster's center) + for key, value in id_clus_dist.items(): + no_points_clus = sum(1 for v in value if v) # How many points/cluster + clus_perc = (no_points_clus / len(X)) * 100 # percentage of points per cluster + + # in the last dict "id_clus_dist" each key (cluster's id) has several dicts that contain information of network's id and distance, + # the below code just to split the sub dicts and merge them as items in anothe single dict + id_dist = {} + for value_1 in value: + id_dist.update(value_1) + + # returns the shortest distance point (selected network) to cluster's center + short_dist_net_id_dist = min(id_dist.items(), key=lambda x: x[1]) + + # Exporting CSV sheet for every cluster that contains the assigned points (networks) and siatance from each to cluster's center + daf = pd.DataFrame() + daf['Network_id'] = id_dist.keys() + daf['Distance_to_cluster_center'] = id_dist.values() +# daf.to_csv('Cluster_No_{}.csv'.format(key), sep=',') + + # export to lists + cluster_id.append(key) # cluster id + cluster_points.append(no_points_clus) # No of points / cluster + clus_percentage.append(round(clus_perc,2)) # Percentage of points per cluster, # round(), two digits after comma + + # the nearest point to cluster center (represented network), there is [0] because it is a tuple + closest_point.append(short_dist_net_id_dist[0]) + + # exporting results to CSV file that contains cluster's id, the no. of assigned points (networks) and the selected network + d = {'CLuster_id': cluster_id, 'no_of_points_per_cluster': cluster_points, + 'cluster_percentage': clus_percentage, + 'the_selected_network_id': closest_point} + df = pd.DataFrame(d) +# df.to_csv('Selected_networks_{}_clusters_dec.csv'.format(no_clusters), sep=',') + + return df + +# # Initiation of 3d graph for scattering plot +# fig = plt.figure() +# fig.suptitle('KMeans clustering', fontsize=20) +# ax = fig.add_subplot(111, projection='3d') +# +# # 3d scatter Plot +# colors = cm.spectral(cluster_labels.astype(float) / no_clusters) +# ax.scatter(X[:, 0], X[:, 1], X[:, 2], alpha=0.3, c=colors) +# +# # Clusters centers 3d scatter plot +# ax.scatter(centroids[:, 0], centroids[:, 1], centroids[:, 2], marker='x', alpha=1, s=50, linewidths=5, zorder=10,c='r') +# +# #limiting the axes scale +# ax.set_xlim(0, 1) +# ax.set_ylim(0, 1) +# ax.set_zlim(0, 1) +# +# # show 3d scatter clustering +# plt.show() +# +# # as for this example where no. of clusters is 20, the results should show 21 CSV files (20 for clusters and 1 for the selected netorks) \ No newline at end of file From 56eec66bdab46451cf430a5742da953a46e9dd23 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 11:56:05 +0200 Subject: [PATCH 176/314] update file --- ego/tools/io.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 0bff7acc..61b417e9 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -175,17 +175,18 @@ def __init__(self, jsonpath, *args, **kwargs): logger.info('Create eTraGo network') self.etrago_network = etrago(self.json_file['eTraGo']) - # add selected results to Results container - self.etrago = pd.DataFrame() - self.etrago.generator = pd.DataFrame() - self.etrago.storage_charges = total_storage_charges(self.etrago_network) - self.etrago.storage_costs = etrago_storages(self.etrago_network) - self.etrago.operating_costs = etrago_operating_costs( - self.etrago_network) - self.etrago.generator = create_etrago_results(self.etrago_network, - self.scn_name) - self.etrago.grid_costs = etrago_grid_investment(self.etrago_network, - self.json_file) + # add selected results to Results container + self.etrago = pd.DataFrame() + self.etrago.generator = pd.DataFrame() + self.etrago.storage_charges = total_storage_charges( + self.etrago_network) + self.etrago.storage_costs = etrago_storages(self.etrago_network) + self.etrago.operating_costs = etrago_operating_costs( + self.etrago_network) + self.etrago.generator = create_etrago_results(self.etrago_network, + self.scn_name) + self.etrago.grid_costs = etrago_grid_investment(self.etrago_network, + self.json_file) # add functions direct # self.etrago_network.etrago_line_loading = etrago_line_loading From a05c3dc13d7ac4130b1346dcf5ee64e49059c36d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 11:56:30 +0200 Subject: [PATCH 177/314] update file --- ego/tools/economics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 930830ed..e4bad419 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -169,7 +169,7 @@ def etrago_grid_investment(network, json_file): .. code-block:: python >>> from ego.tools.io import eGo - >>> ego = eGo(jsonpath='scenario_setting.json' + >>> ego = eGo(jsonpath='scenario_setting.json') >>> ego.etrago.grid_costs +-----+---------------------+----------------+-----------+ From a4a5056044ca3e356973368fb9c59bb7af1d3bd9 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 14:25:21 +0200 Subject: [PATCH 178/314] change import for carrier names --- ego/tools/io.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 61b417e9..2de441cf 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -464,6 +464,14 @@ def map_ormclass(name): return _mapped + def id_to_source(query): + + # ormclass = map_ormclass(name) + # query = session.query(ormclass).filter(ormclass.result_id == result_id) + + # TODO column naming in database + return {k.source_id: k.name for k in query.all()} + def dataframe_results(name, session, result_id, ormclass): """ Function to get pandas DataFrames by the result_id @@ -483,6 +491,18 @@ def dataframe_results(name, session, result_id, ormclass): session.bind, index_col=name.lower() + '_id') + if name == 'Link': + df['bus0'] = df.bus0.astype(int) + df['bus1'] = df.bus1.astype(int) + + if 'source' in df: + + source_orm = Source + + source_query = session.query(source_orm) + + df.source = df.source.map(id_to_source(source_query)) + if str(ormclass)[:-2].endswith('T'): df = pd.Dataframe() @@ -494,7 +514,7 @@ def series_results(name, column, session, meta_args, result_id, ormclass): Parameters ---------- - session : :sqlalchemy:`sqlalchemy.orm.session.Session` + session: : sqlalchemy: `sqlalchemy.orm.session.Session < orm/session_basics.html >` SQLAlchemy session to the OEDB ToDo @@ -587,7 +607,7 @@ def recover_resultsettings(session, json_file, orm_meta): _mapped = {} # get metadata - #version = json_file['global']['gridversion'] + # version = json_file['global']['gridversion'] orm_meta = getattr(_pkg, _prefix + 'Meta') @@ -721,6 +741,12 @@ def recover_resultsettings(session, json_file, orm_meta): print("Series %s of component %s could not be " "imported" % (col, pypsa_comp_name)) + # populate carrier attribute in PyPSA network + # network.import_components_from_dataframe( + # self.fetch_by_relname(carr_ormclass), 'Carrier') + + # add fetch_by_relname and + print('Done') logger.info('Imported eTraGo results of id = %s ', result_id) return network From f42aa912af40e2ba50d8218ca75d0110615c4a71 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 15:07:44 +0200 Subject: [PATCH 179/314] git remove json_file by oedb results parameter --- ego/tools/io.py | 172 +++++++++++++++++++++--------------------------- 1 file changed, 76 insertions(+), 96 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 2de441cf..ee58ab59 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -38,13 +38,15 @@ from geoalchemy2 import * from egoio.tools import db + from etrago.tools.io import load_config_file + from egoio.db_tables.model_draft import EgoGridPfHvSource as Source,\ + EgoGridPfHvTempResolution as TempResolution from tools.results import (create_etrago_results) from tools.storages import (total_storage_charges, etrago_storages) from tools.economics import (etrago_operating_costs, etrago_grid_investment, edisgo_grid_investment, investment_costs, get_generator_investment) from tools.utilities import get_scenario_setting, get_time_steps - from etrago.appl import etrago from egoio.db_tables.model_draft import RenpassGisParameterRegion from egoio.db_tables import model_draft, grid from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, @@ -53,6 +55,9 @@ plot_line_loading_diff, full_load_hours, extension_overlay_network) from etrago.appl import etrago + from importlib import import_module + import pypsa + import re __copyright__ = ("Europa-Universität Flensburg, " "Centre for Sustainable Energy Systems") @@ -161,8 +166,22 @@ def __init__(self, jsonpath, *args, **kwargs): # ToDo add scenario_setting for results self.json_file['eTraGo']['db'] = self.json_file['global']['db'] logger.info( - 'Add `eTraGo` scenario_setting from oedb result') + 'Add eTraGo scenario_setting from oedb result') # To do .... + _prefix = 'EgoGridPfHvResult' + schema = 'model_draft' + packagename = 'egoio.db_tables' + _pkg = import_module(packagename + '.' + schema) + + # get metadata + # version = json_file['global']['gridversion'] + + orm_meta = getattr(_pkg, _prefix + 'Meta') + self.jsonpath = recover_resultsettings(self.session, + self.json_file, + orm_meta, + self.json_file['global'] + ['result_id']) except KeyError: pass @@ -175,18 +194,18 @@ def __init__(self, jsonpath, *args, **kwargs): logger.info('Create eTraGo network') self.etrago_network = etrago(self.json_file['eTraGo']) - # add selected results to Results container - self.etrago = pd.DataFrame() - self.etrago.generator = pd.DataFrame() - self.etrago.storage_charges = total_storage_charges( - self.etrago_network) - self.etrago.storage_costs = etrago_storages(self.etrago_network) - self.etrago.operating_costs = etrago_operating_costs( - self.etrago_network) - self.etrago.generator = create_etrago_results(self.etrago_network, - self.scn_name) - self.etrago.grid_costs = etrago_grid_investment(self.etrago_network, - self.json_file) + # add selected results to Results container + self.etrago = pd.DataFrame() + self.etrago.generator = pd.DataFrame() + self.etrago.storage_charges = total_storage_charges( + self.etrago_network) + self.etrago.storage_costs = etrago_storages(self.etrago_network) + self.etrago.operating_costs = etrago_operating_costs( + self.etrago_network) + self.etrago.generator = create_etrago_results(self.etrago_network, + self.scn_name) + self.etrago.grid_costs = etrago_grid_investment(self.etrago_network, + self.json_file) # add functions direct # self.etrago_network.etrago_line_loading = etrago_line_loading @@ -439,17 +458,8 @@ def etrago_from_oedb(session, json_file): add Mapping for grid schema make it more generic -> class? """ - result_id = json_file['global']['result_id'] - # modules from model_draft - from egoio.db_tables.model_draft import EgoGridPfHvSource as Source,\ - EgoGridPfHvTempResolution as TempResolution - from etrago.tools.io import load_config_file - from importlib import import_module - import pypsa - import re - import logging - logger = logging.getLogger('ego') + result_id = json_file['global']['result_id'] # functions def map_ormclass(name): @@ -508,7 +518,7 @@ def dataframe_results(name, session, result_id, ormclass): return df - def series_results(name, column, session, meta_args, result_id, ormclass): + def series_results(name, column, session, result_id, ormclass): """ Function to get Time Series as pandas DataFrames by the result_id @@ -551,47 +561,6 @@ def series_results(name, column, session, meta_args, result_id, ormclass): return df - def recover_resultsettings(session, json_file, orm_meta): - """ Recover scenario_setting from database - """ - - # check result_id - result_id_in = session.query( - orm_meta.result_id).filter(orm_meta. - result_id == result_id).all() - if result_id_in: - logger.info('Choosen result_id %s found in DB', result_id) - else: - logger.info('Error: result_id not found in DB') - - # get meta data as json_file - meta = session.query(orm_meta.result_id, orm_meta.scn_name, orm_meta.calc_date, - orm_meta.user_name, orm_meta.method, orm_meta.start_snapshot, - orm_meta.end_snapshot, orm_meta.solver, orm_meta.settings - ).filter(orm_meta.result_id == result_id) - - meta_df = pd.read_sql( - meta.statement, meta.session.bind, index_col='result_id') - - # update json_file with main data by result_id - json_file['eTraGo']['scn_name'] = meta_df.scn_name[result_id] - json_file['eTraGo']['method'] = meta_df.method[result_id] - json_file['eTraGo']['start_snapshot'] = meta_df.start_snapshot[result_id] - json_file['eTraGo']['end_snapshot'] = meta_df.end_snapshot[result_id] - json_file['eTraGo']['solver'] = meta_df.solver[result_id] - - # update json_file with specific data by result_id - meta_set = dict(meta_df.settings[result_id]) - - for key in json_file['eTraGo'].keys(): - - try: - json_file['eTraGo'][key] = meta_set[key] - except KeyError: - pass - - return json_file - # create config for results path = os.getcwd() # add meta_args with args of results @@ -622,20 +591,7 @@ def recover_resultsettings(session, json_file, orm_meta): logger.info('Error: result_id not found in DB') # get meta data as args - meta = session.query(orm_meta.result_id, orm_meta.scn_name, orm_meta.calc_date, - orm_meta.user_name, orm_meta.method, orm_meta.start_snapshot, - orm_meta.end_snapshot, orm_meta.solver, orm_meta.settings - ).filter(orm_meta.result_id == result_id) - - meta_df = pd.read_sql( - meta.statement, meta.session.bind, index_col='result_id') - - meta_args = dict(meta_df.settings[result_id]) - meta_args['scn_name'] = meta_df.scn_name[result_id] - meta_args['method'] = meta_df.method[result_id] - meta_args['start_snapshot'] = meta_df.start_snapshot[result_id] - meta_args['end_snapshot'] = meta_df.end_snapshot[result_id] - meta_args['solver'] = meta_df.solver[result_id] + meta_args = recover_resultsettings(session, json_file, orm_meta, result_id) # get TempResolution temp = TempResolution @@ -647,15 +603,8 @@ def recover_resultsettings(session, json_file, orm_meta): periods=tr.timesteps, freq=tr.resolution) - timeindex = timeindex[meta_args['start_snapshot'] - - 1: meta_args['end_snapshot']] - - meta_args['temp_id'] = tr.temp_id - print(meta_args) - print('und das neue') - - meta_test = recover_resultsettings(session, json_file, orm_meta) - print(meta_test) + timeindex = timeindex[meta_args['eTraGo']['start_snapshot'] - + 1: meta_args['eTraGo']['end_snapshot']] # create df for PyPSA network @@ -721,7 +670,7 @@ def recover_resultsettings(session, json_file, orm_meta): for col in columns: df_series = series_results( - name, col, session, meta_args, result_id, ormclass) + name, col, session, result_id, ormclass) # TODO: VMagPuSet? if timevarying_override and comp == 'Generator': @@ -741,16 +690,47 @@ def recover_resultsettings(session, json_file, orm_meta): print("Series %s of component %s could not be " "imported" % (col, pypsa_comp_name)) - # populate carrier attribute in PyPSA network - # network.import_components_from_dataframe( - # self.fetch_by_relname(carr_ormclass), 'Carrier') - - # add fetch_by_relname and - print('Done') logger.info('Imported eTraGo results of id = %s ', result_id) return network +def recover_resultsettings(session, json_file, orm_meta, result_id): + """ Recover scenario_setting from database + """ + + # check result_id + result_id_in = session.query( + orm_meta.result_id).filter(orm_meta. + result_id == result_id).all() + + # get meta data as json_file + meta = session.query(orm_meta.result_id, orm_meta.scn_name, orm_meta.calc_date, + orm_meta.user_name, orm_meta.method, orm_meta.start_snapshot, + orm_meta.end_snapshot, orm_meta.solver, orm_meta.settings + ).filter(orm_meta.result_id == result_id) + + meta_df = pd.read_sql( + meta.statement, meta.session.bind, index_col='result_id') + + # update json_file with main data by result_id + json_file['eTraGo']['scn_name'] = meta_df.scn_name[result_id] + json_file['eTraGo']['method'] = meta_df.method[result_id] + json_file['eTraGo']['start_snapshot'] = meta_df.start_snapshot[result_id] + json_file['eTraGo']['end_snapshot'] = meta_df.end_snapshot[result_id] + json_file['eTraGo']['solver'] = meta_df.solver[result_id] + + # update json_file with specific data by result_id + meta_set = dict(meta_df.settings[result_id]) + + for key in json_file['eTraGo'].keys(): + try: + json_file['eTraGo'][key] = meta_set[key] + except KeyError: + pass + + return json_file + + if __name__ == '__main__': pass From 58c020ed0bbfc6565180aac08bf34f007a7308c4 Mon Sep 17 00:00:00 2001 From: maltesc Date: Thu, 12 Jul 2018 15:29:03 +0200 Subject: [PATCH 180/314] pooling test --- ego/scenario_setting.json | 12 ++--- ego/tools/edisgo_integration.py | 85 ++++++++++++++++++++++++++------- ego/tools/io.py | 2 +- ego/tools/specs.py | 2 +- 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index cecf275e..7b582a58 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -4,14 +4,14 @@ "eDisGo": false, "db": "oedb", "result_id": 26, - "recover": true, + "recover": false, "gridversion": "v0.4.2" }, "eTraGo": { "method": "lopf", "pf_post_lopf": false, - "start_snapshot": 2952, - "end_snapshot" : 2966, + "start_snapshot": 1, + "end_snapshot" : 2, "solver": "gurobi", "solver_options":{}, "scn_name": "NEP 2035", @@ -21,12 +21,11 @@ "lpfile": false, "results": false, "export": false, - "extendable": null, + "extendable": [], "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, "network_clustering_kmeans": false, - "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, @@ -39,7 +38,8 @@ }, "eDisGo": { "specs": true, - "ding0_files": "data/MV_grids/20180705104811", + "ding0_files": "data/MV_grids/20180712120156", + "mv_cluster": 2, "scn_name": "NEP 2035", "comments": "make a comment" } diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 11d55dc1..dc35c39a 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -16,8 +16,10 @@ from egoio.db_tables import model_draft, grid from egoio.tools import db from edisgo.grid.network import Results, TimeSeriesControl +from edisgo.tools.pypsa_io import update_pypsa_timeseries from edisgo.tools.edisgo_run import ( - run_edisgo_basic + run_edisgo_basic, + run_edisgo_pool_flexible ) from ego.tools.specs import ( get_etragospecs_direct, @@ -31,12 +33,20 @@ ## Other Packages import os import logging +import pandas as pd from sqlalchemy.orm import sessionmaker # Logging logging.basicConfig(format='%(asctime)s %(message)s',level=logging.INFO) logger = logging.getLogger(__name__) + +#os.getcwd() +#os.chdir('/home/student/Git/eGo/ego/') + +def test_pool(a, b): + print('hallo') + class EDisGoNetworks: """ Represents multiple eDisGo networks. @@ -91,7 +101,7 @@ def cluster_mv_grids(self, no_grids): logger.info('Attributes will be calculated') self.analyze_cluster_attributes() - self._cluster = cluster_mv_grids(self._ding0_files, no_grids) + return cluster_mv_grids(self._ding0_files, no_grids) def check_available_mv_grids(self): @@ -105,13 +115,28 @@ def check_available_mv_grids(self): return mv_grids + def run_edisgo_pool(self, parallelization=False): - def run_edisgo(self, mv_grid_id): + + if parallelization is True: + + raise NotImplementedError +# id_list = self._cluster['the_selected_network_id'].tolist() +# +# self._pool = run_edisgo_pool_flexible( +# ding0_id_list=id_list, +# func=test_pool, +# func_arguments=['toll']) + + else: + + + def run_edisgo(self, mv_grid_id, *args): """ Runs eDisGo with the desired settings. """ - + logger.info('Calculating interface values') bus_id = self.get_bus_id_from_mv_grid(mv_grid_id) @@ -142,31 +167,50 @@ def run_edisgo(self, mv_grid_id): analysis='worst-case') logger.info('eTraGo feed-in case') - edisgo_grid.network.results = Results() - edisgo_grid.network.pypsa = None - if self._generator_scn: - edisgo_grid.import_generators( - generator_scenario=self._generator_scn) - + edisgo_grid.network.results = Results() +# edisgo_grid.network.pypsa = None +# +# if self._generator_scn: +# edisgo_grid.import_generators( +# generator_scenario=self._generator_scn) + logger.warning('No generators are imported') + edisgo_grid.network.timeseries = TimeSeriesControl( # Here, I use only normalized values from specs timeseries_generation_fluctuating=specs['potential'], timeseries_generation_dispatchable=specs['conv_dispatch'], timeseries_load='demandlib', - weather_cell_ids=edisgo_grid.network.mv_grid._weather_cells, config_data=edisgo_grid.network.config, timeindex=specs['conv_dispatch'].index).timeseries - + + update_pypsa_timeseries( + edisgo_grid.network, + timesteps=specs['conv_dispatch'].index) + # edisgo_grid.curtail(curtailment_methodology='curtail_all', # # Here, I use absolute values # timeseries_curtailment=specs['curtailment_abs']) - # Think about the other curtailment functions!!!! +# +# # Think about the other curtailment functions!!!! + + edisgo_grid.analyze() - edisgo_grid.network.pypsa = None + edisgo_grid.reinforce() + + # Get costs + costs_grouped = \ + edisgo_grid.network.results.grid_expansion_costs.groupby( + ['type']).sum() + costs = pd.DataFrame(costs_grouped.values, + columns=costs_grouped.columns, + index=[[edisgo_grid.network.id] * len(costs_grouped), + costs_grouped.index]).reset_index() + costs.rename(columns={'level_0': 'grid'}, inplace=True) - edisgo_grid.analyze() + # Grid issues besser verstehen!! Und evtl. mit aussgeben + return edisgo_grid ## Helpful tools @@ -239,6 +283,15 @@ def get_hvmv_translation(self): json_file=ego.json_file, etrago_network=ego.etrago_network) -test.run_edisgo(mv_grid_id=1729) +#grid = test.run_edisgo(mv_grid_id=1729) +test.cluster_mv_grids(2) + + +test.run_edisgo_pool(parallelization=False) + + + +#ret.network.mv_grid.graph. + diff --git a/ego/tools/io.py b/ego/tools/io.py index 774e5111..023d7b11 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -291,7 +291,7 @@ def __init__(self, jsonpath, *args, **kwargs): if self.json_file['global']['eDisGo'] is True: logger.info('Create eDisGo network') - self.edisgo_network = None # add eDisGo initialisation here + self.edisgo_networks = None # add eDisGo initialisation here pass diff --git a/ego/tools/specs.py b/ego/tools/specs.py index 402c6145..e4cc2d9f 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -465,7 +465,7 @@ def get_etragospecs_direct(session, all_gens_df.at[index, 'name'] = 'wind' logger.warning('wind onshore is renamed to wind') -# print(all_gens_df) + print(all_gens_df) # names = [] # for index, row in all_gens_df.iterrows(): # carrier = row['carrier'] From d938fe6acafc7bfcaa9144cbee60eb20203047b8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 15:32:54 +0200 Subject: [PATCH 181/314] update release note --- doc/whatsnew/v0-2-0.rst | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index 2b4d0a9e..212e6282 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -1,7 +1,7 @@ -Release v0.2.0 (July 13, 2018) +Release v0.2.0 (July 17, 2018) ++++++++++++++++++++++++++++++ -The second release of the eGo application. +Second release of the eGo application. New features have been included in this release. Major changes being the new class structure and separation of methods into the given file structure. @@ -18,22 +18,37 @@ Added features -------------- * Cleaned and restructured eGo classes and functions -** Moved classes of eGo from results.py to io.py - -* Updated eTraGo 0.6 and integrated new functions and features to eGo + - Moved classes of eGo from results.py to io.py + - Move serveral function + - Introduce new files for edisgo handling: + - edisgo_integration.py + - mv_cluster.py + - Introduce new file storages.py for eTraGo +* Updated eTraGo 0.6 and integrated eTraGo's new functions and features to eGo * Updated eDisGo 0.0.3 version which includes the features of a parallelization for custom function and other important API changes. -* Implemented pep8 style to eGo Code -* Implemented logging function for the hole model +* Started to implemented pep8 style to eGo Code +* Implemented logging function for the whole model * Using the Restfull-API for the OpenEnergy Database connection, buy using ego.io v0.4.2. A registration is needed and can be done on `openenergy-platform.org/login `_ -* Introduce new file storages.py and xxx edisgo.py -* Remove functionalities from main to the eGo class -* ... +* Remove functionalities from ``ego_main.py`` to the eGo class +* Fixed eTraGo scenario import of ``etrago_from_oedb()`` + + +ToDo's bis Release +------------------ + +* mv clustering for eDisGo / Ding0 grids +* cost manipulation / skalling of global costs +* all costs "over night" grid/storages (annuisiert) +* Plot der Gesamt investkosten +* operational costs edisgo ? | pro Ebene +* operational costs eTragGo | pro Ebene + Notes ----- * As an external user you need to have and account on the `openenergy-platform.org/login `_ -* ... +* Total operational costs are missing in this release From e40d4469a29656f76211f1f3e3945ac9d69d10ef Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 15:36:13 +0200 Subject: [PATCH 182/314] change of size --- doc/theoretical_background.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/theoretical_background.rst b/doc/theoretical_background.rst index 28fe89b9..55a5557c 100644 --- a/doc/theoretical_background.rst +++ b/doc/theoretical_background.rst @@ -4,6 +4,11 @@ Theoretical background + + + + + Models overview ================ @@ -11,7 +16,7 @@ Models overview .. figure:: images/open_ego_models_overview.png :width: 1123px :height: 794px - :scale: 95% + :scale: 70% :alt: Overview of Models and processes which are used by eGo :align: center From 89683358aa4bf1d63ff8b6532c0a595c578469ed Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 15:44:21 +0200 Subject: [PATCH 183/314] update file --- doc/theoretical_background.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/theoretical_background.rst b/doc/theoretical_background.rst index 55a5557c..41003551 100644 --- a/doc/theoretical_background.rst +++ b/doc/theoretical_background.rst @@ -6,9 +6,6 @@ Theoretical background - - - Models overview ================ @@ -22,5 +19,7 @@ Models overview + + References ========== From f55129f71bc7fee4851f0fd6adbec6d36435ab15 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 16:27:53 +0200 Subject: [PATCH 184/314] change settings --- ego/scenario_setting.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 94a67ef6..40b88ec6 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -4,14 +4,14 @@ "eDisGo": false, "db": "oedb", "result_id": 26, - "recover": true, + "recover": false, "gridversion": "v0.4.2" }, "eTraGo": { "method": "lopf", "pf_post_lopf": false, "start_snapshot": 2952, - "end_snapshot" : 2966, + "end_snapshot" : 2953, "solver": "gurobi", "solver_options":{}, "scn_name": "NEP 2035", @@ -22,10 +22,10 @@ "results": false, "export": false, "extendable": "['network', 'storages']", - "generator_noise": false, + "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": 100, + "network_clustering_kmeans": false, "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, @@ -33,7 +33,7 @@ "skip_snapshots": false, "line_grouping": false, "branch_capacity_factor": 1, - "load_shedding": false, + "load_shedding": true, "comments": null }, "eDisGo": { From 9efd14f7babd46546235758541ed93bf6dcb7482 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 16:32:45 +0200 Subject: [PATCH 185/314] add license --- doc/welcome.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/welcome.rst b/doc/welcome.rst index 3d4c8ef1..75b73249 100644 --- a/doc/welcome.rst +++ b/doc/welcome.rst @@ -32,3 +32,31 @@ grid data for whole Germany. Learn more about `eTraGo `_, `eDisGo `_ and the `OpenEnergy Platform `_ which are part of the open_eGo project. + + +LICENSE +======= + +© Copyright 2015-2018 + +Flensburg University of Applied Sciences, + +Europa-Universität Flensburg, + +Centre for Sustainable Energy Systems + + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for +more details. + +You should have received a copy of the GNU General Public License along +with this program. +If not, see `www.gnu.org/licenses `_. + From 037b26a408cd04569111647cef3504d378e894a0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 17:04:48 +0200 Subject: [PATCH 186/314] add docu --- doc/index.rst | 3 +- doc/installation.rst | 111 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 doc/installation.rst diff --git a/doc/index.rst b/doc/index.rst index 29270e93..f7011cc7 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -15,12 +15,11 @@ Welcome to eGo documentation! `openenergy-platform.org/login `_. - - .. toctree:: :maxdepth: 3 welcome + installation getting_started usage_details theoretical_background diff --git a/doc/installation.rst b/doc/installation.rst new file mode 100644 index 00000000..5d91ac6b --- /dev/null +++ b/doc/installation.rst @@ -0,0 +1,111 @@ +============ +Installation +============ +eGo is designed as a Python package therefore it is mandatory to have +`Python 3 `_ installed. If you have a +working Python3 environment, use pypi to install the latest eGo version. +We highly recommend you to use a virtual environment. Use following pip +command in order to install eGo: + +.. code-block:: bash + + $ pip3 install eGo --process-dependency-links + + + +Using virtual environment +========================= + +Firstly, you create a virtual environment (where you like it) and activate it: + +.. code-block:: bash + + $ virtualenv venv --clear -p python3.5 + $ source venv/bin/activate + $ cd venv + +Inside your virtual environment you can install eGo with the pip command. + +Linux and Ubuntu +================ + +The Package eGo is tested with Ubuntu 16.04 and 18.04 inside the virtual +environments of `virtualenv `_. +The installation is shown above. + + + +Windows or Mac OSX users +======================== + +For Windows and/or Mac OSX user we highly recommend to install and use Anaconda +for you Python3 installation. First install anaconda inclusing python 3.5 or +higher version from https://www.anaconda.com/download/ and open an anaconda +prompt as administrator and run: + +.. code-block:: bash + + $ conda install pip + $ conda config --add channels conda-forge + $ conda install shapely + $ pip3 install eGo --process-dependency-links + +The full Documentation can be found +`on this page `_ . We use Anaconda +with an own environment in order to reduze problems with Packages and different +versions on our system. Learn more about +`Anacona `_ +environments. + + + +Setup database connection +========================= +The package ``ego.io`` gives you a python SQL-Alchemy representations of +the _OpenEnergy-Database_ (oedb) and access to it by using the +`oedialect `_ a SQL-Alchemy binding +Python package for the REST-API used by the OpenEnergy Platform (OEP). Your API +access / login data will be saved in the folder ``.egoio`` in the file +``config.ini``. You can create a new account on +`openenergy-platform.org/login `_. + + +oedialect connection +-------------------- + +.. code-block:: desktop + + [oedb] + dialect = oedialect + username = + database = oedb + host = openenergy-platform.org + port = 80 + password = + + +Local database connection +------------------------- + +.. code-block:: desktop + + [local] + username = YourOEDBUserName + database = YourLocalDatabaseName + host = localhost or 127.0.0.1 + port = 5433 + pw = YourLocalPassword + + + +Old developer connection +------------------------ + +.. code-block:: desktop + + [oedb] + username = YourOEDBUserName + database = oedb + host = oe2.iws.cs.ovgu.de + port = 5432 + pw = YourOEDBPassword From 2a57b7f419e4e513edcc90e6c51cf52e7583c20a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 17:05:39 +0200 Subject: [PATCH 187/314] change class and and new pyomo version --- ego/tools/io.py | 26 +++++++++++++++----------- setup.py | 1 + 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index ee58ab59..14825c32 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -110,15 +110,6 @@ def __init__(self, pass - def __repr__(self): - - r = ('eGoResults is created.') - if not self.etrago_network: - r += "\nThe results does not incluede eTraGo results" - if not self.edisgo_network: - r += "\nThe results does not incluede eDisGo results" - return r - pass @@ -151,6 +142,8 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago_network = None + logger.info('eTraGoResults startet') + if self.json_file['global']['recover'] is True: # Delete arguments from scenario_setting @@ -289,7 +282,7 @@ def etrago_full_load_hours(self, **kwargs): # add other methods from eTraGo here -class eDisGoResults(egoBasic): +class eDisGoResults(eTraGoResults): """ eDisGo Results This module contains all results of eDisGo for eGo. @@ -304,19 +297,22 @@ class eDisGoResults(egoBasic): def __init__(self, jsonpath, *args, **kwargs): super(eDisGoResults, self).__init__(self, jsonpath, *args, **kwargs) + logger.info('eDisGoResults startet') + self.edisgo_network = None self.edisgo = pd.DataFrame() if self.json_file['global']['eDisGo'] is True: logger.info('Create eDisGo network') self.edisgo_network = None # add eDisGo initialisation here + self.hansOS = self.etrago_network pass pass -class eGo(eTraGoResults, eDisGoResults): +class eGo(eDisGoResults): """Main eGo module which including all results and main functionalities. @@ -342,6 +338,14 @@ def __init__(self, jsonpath, *args, **kwargs): # add all ego function pass + def __repr__(self): + r = ('eGoResults is created.') + if not self.etrago_network: + r += "\nThe results does not incluede eTraGo results" + if not self.edisgo_network: + r += "\nThe results does not incluede eDisGo results" + return r + # write_results_to_db(): logging.info('Initialisation of eGo Results') diff --git a/setup.py b/setup.py index 47d4c9f3..9412e04a 100644 --- a/setup.py +++ b/setup.py @@ -37,6 +37,7 @@ def read(fname): 'matplotlib>= 1.5.3, <=1.5.3', 'Rtree==0.8.3', 'plotly==2.2.3', + 'Pyomo==5.5.0', 'oedialect' ], dependency_links=[('git+https://git@github.com/openego/PyPSA.git' From 7fb638be1c432e4e8f296bc6c90c3b39097f581b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 12 Jul 2018 17:09:55 +0200 Subject: [PATCH 188/314] update file --- doc/welcome.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/welcome.rst b/doc/welcome.rst index 75b73249..71449a54 100644 --- a/doc/welcome.rst +++ b/doc/welcome.rst @@ -40,9 +40,7 @@ LICENSE © Copyright 2015-2018 Flensburg University of Applied Sciences, - Europa-Universität Flensburg, - Centre for Sustainable Energy Systems From e38708eaecc8be6a3a19990bb9112bbbaf3bac12 Mon Sep 17 00:00:00 2001 From: maltesc Date: Thu, 12 Jul 2018 17:37:39 +0200 Subject: [PATCH 189/314] pooling tests --- ego/scenario_setting.json | 4 +- ego/tools/edisgo_integration.py | 99 ++++++++++++++++++++++----------- ego/tools/io.py | 12 ++-- 3 files changed, 73 insertions(+), 42 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 7b582a58..b7b2aa75 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -4,7 +4,7 @@ "eDisGo": false, "db": "oedb", "result_id": 26, - "recover": false, + "recover": true, "gridversion": "v0.4.2" }, "eTraGo": { @@ -39,7 +39,7 @@ "eDisGo": { "specs": true, "ding0_files": "data/MV_grids/20180712120156", - "mv_cluster": 2, + "mv_cluster": null, "scn_name": "NEP 2035", "comments": "make a comment" } diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index dc35c39a..045f0cb3 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -33,6 +33,7 @@ ## Other Packages import os import logging +import multiprocessing as mp import pandas as pd from sqlalchemy.orm import sessionmaker @@ -40,12 +41,6 @@ logging.basicConfig(format='%(asctime)s %(message)s',level=logging.INFO) logger = logging.getLogger(__name__) - -#os.getcwd() -#os.chdir('/home/student/Git/eGo/ego/') - -def test_pool(a, b): - print('hallo') class EDisGoNetworks: """ @@ -59,14 +54,16 @@ def __init__(self, **kwargs): Session = sessionmaker(bind=conn) self._session = Session() + ## Json Inputs self._json_file = kwargs.get('json_file', None) - self._grid_version = self._json_file['global']['gridversion'] - self._edisgo_args = self._json_file['eDisGo'] + ### eDisGo args + self._edisgo_args = self._json_file['eDisGo'] self._ding0_files = self._edisgo_args['ding0_files'] - self._scn_name = self._edisgo_args['scn_name'] - + self._mv_cluster = self._edisgo_args['mv_cluster'] + + self._scn_name = self._edisgo_args['scn_name'] if self._scn_name == 'Status Quo': self._generator_scn = None elif self._scn_name == 'NEP 2035': @@ -79,7 +76,12 @@ def __init__(self, **kwargs): else: self._versioned = False + ## eTraGo self._etrago_network = kwargs.get('etrago_network', None) + + ## Functions + self.grid_choice() + self.run_edisgo_pool() def analyze_cluster_attributes(self): @@ -89,7 +91,7 @@ def analyze_cluster_attributes(self): """ analyze_attributes(self._ding0_files) - def cluster_mv_grids(self, no_grids): + def cluster_mv_grids(self): """ Clusters the MV grids based on the attributes @@ -101,7 +103,7 @@ def cluster_mv_grids(self, no_grids): logger.info('Attributes will be calculated') self.analyze_cluster_attributes() - return cluster_mv_grids(self._ding0_files, no_grids) + return cluster_mv_grids(self._ding0_files, self._mv_cluster) def check_available_mv_grids(self): @@ -115,12 +117,29 @@ def check_available_mv_grids(self): return mv_grids - def run_edisgo_pool(self, parallelization=False): + def grid_choice(self): + if self._mv_cluster: + logger.info('Clustering to {} MV grids'.format(self._mv_cluster)) + cluster = self.cluster_mv_grids() + else: + mv_grids = self.check_available_mv_grids() + cluster = pd.DataFrame( + mv_grids, + columns=['the_selected_network_id']) + cluster['no_of_points_per_cluster'] = 1 + no_grids = len(mv_grids) + logger.info( + 'Calculating all available {} MV grids'.format(no_grids) + ) + self._grid_choice = cluster + def run_edisgo_pool(self, parallelization=True): + if parallelization is True: - + logger.info('Parallelization') raise NotImplementedError + # id_list = self._cluster['the_selected_network_id'].tolist() # # self._pool = run_edisgo_pool_flexible( @@ -130,7 +149,33 @@ def run_edisgo_pool(self, parallelization=False): else: - + self._edisgo_grids = {} + + no_grids = len(self._grid_choice) + count = 0 + for idx, row in self._grid_choice.iterrows(): + prog = '%.1f' % (count / no_grids * 100) + logger.info( + '{} % Calculated by eDisGo'.format(prog) + ) + + mv_grid_id = int(row['the_selected_network_id']) + logger.info( + 'MV grid {}'.format(mv_grid_id) + ) + try: + self._edisgo_grids[ + mv_grid_id + ] = self.run_edisgo(mv_grid_id) + except: + self._edisgo_grids[mv_grid_id] = None + logger.info( + 'MV grid {} failed'.format(mv_grid_id) + ) + + count += 1 + + def run_edisgo(self, mv_grid_id, *args): """ Runs eDisGo with the desired settings. @@ -187,7 +232,8 @@ def run_edisgo(self, mv_grid_id, *args): update_pypsa_timeseries( edisgo_grid.network, timesteps=specs['conv_dispatch'].index) - + + logger.warning('Curtailment can only be included after gen import') # edisgo_grid.curtail(curtailment_methodology='curtail_all', # # Here, I use absolute values # timeseries_curtailment=specs['curtailment_abs']) @@ -275,23 +321,8 @@ def get_hvmv_translation(self): raise NotImplementedError - - - - test = EDisGoNetworks( json_file=ego.json_file, - etrago_network=ego.etrago_network) - -#grid = test.run_edisgo(mv_grid_id=1729) -test.cluster_mv_grids(2) - - -test.run_edisgo_pool(parallelization=False) - - - -#ret.network.mv_grid.graph. - - - +etrago_network=ego.etrago_network) + +test._edisgo_grids diff --git a/ego/tools/io.py b/ego/tools/io.py index 3920f05c..922f949d 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -47,6 +47,7 @@ edisgo_grid_investment, investment_costs, get_generator_investment) from tools.utilities import get_scenario_setting, get_time_steps +# from tools.edisgo_integration import EDisGoNetworks from egoio.db_tables.model_draft import RenpassGisParameterRegion from egoio.db_tables import model_draft, grid from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, @@ -307,16 +308,15 @@ class eDisGoResults(egoBasic): def __init__(self, jsonpath, *args, **kwargs): super(eDisGoResults, self).__init__(self, jsonpath, *args, **kwargs) - self.edisgo_network = None - self.edisgo = pd.DataFrame() +# self._edisgo_networks = None +# self.edisgo = pd.DataFrame() if self.json_file['global']['eDisGo'] is True: logger.info('Create eDisGo network') - self.edisgo_networks = None # add eDisGo initialisation here +# self.edisgo_networks = EDisGoNetworks( +# json_file=self.json_file, +# etrago_network=self.etrago_network) - pass - - pass class eGo(eTraGoResults, eDisGoResults): From 96d8a1007ceca8b2d93454f99017a06067646cad Mon Sep 17 00:00:00 2001 From: maltesc Date: Thu, 12 Jul 2018 18:05:53 +0200 Subject: [PATCH 190/314] Integration simple case works --- ego/scenario_setting.json | 4 ++-- ego/tools/edisgo_integration.py | 7 +------ ego/tools/io.py | 10 ++++++---- ego/tools/specs.py | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 0409a3c1..40910725 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -1,10 +1,10 @@ { "global": { "eTraGo": true, - "eDisGo": false, + "eDisGo": true, "db": "oedb", "result_id": 26, - "recover": false, + "recover": true, "gridversion": "v0.4.2" }, "eTraGo": { diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 045f0cb3..d90101b3 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -134,7 +134,7 @@ def grid_choice(self): ) self._grid_choice = cluster - def run_edisgo_pool(self, parallelization=True): + def run_edisgo_pool(self, parallelization=False): if parallelization is True: logger.info('Parallelization') @@ -321,8 +321,3 @@ def get_hvmv_translation(self): raise NotImplementedError -test = EDisGoNetworks( - json_file=ego.json_file, -etrago_network=ego.etrago_network) - -test._edisgo_grids diff --git a/ego/tools/io.py b/ego/tools/io.py index 789bf9f3..b3874284 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -47,7 +47,7 @@ edisgo_grid_investment, investment_costs, get_generator_investment) from tools.utilities import get_scenario_setting, get_time_steps -# from tools.edisgo_integration import EDisGoNetworks + from tools.edisgo_integration import EDisGoNetworks from egoio.db_tables.model_draft import RenpassGisParameterRegion from egoio.db_tables import model_draft, grid from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, @@ -303,13 +303,15 @@ def __init__(self, jsonpath, *args, **kwargs): logger.info('eDisGoResults startet') - self.edisgo_network = None +# self.edisgo_networks = None self.edisgo = pd.DataFrame() if self.json_file['global']['eDisGo'] is True: logger.info('Create eDisGo network') - self.edisgo_network = None # add eDisGo initialisation here - self.hansOS = self.etrago_network + self.edisgo_networks = EDisGoNetworks( + json_file=self.json_file, + etrago_network=self.etrago_network) + class eGo(eDisGoResults): diff --git a/ego/tools/specs.py b/ego/tools/specs.py index e4cc2d9f..402c6145 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -465,7 +465,7 @@ def get_etragospecs_direct(session, all_gens_df.at[index, 'name'] = 'wind' logger.warning('wind onshore is renamed to wind') - print(all_gens_df) +# print(all_gens_df) # names = [] # for index, row in all_gens_df.iterrows(): # carrier = row['carrier'] From fa353600eb696e163823371fd079a2bf292083a8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 08:24:43 +0200 Subject: [PATCH 191/314] clean file --- ego/ego_main.py | 150 ++++-------------------------------------------- 1 file changed, 10 insertions(+), 140 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index a8f783e0..69d84603 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -21,10 +21,10 @@ This is the application file for the tool eGo. The application eGo calculates the distribution and transmission grids of eTraGo and eDisGo. -.. warning:: - Note, that this Repository is under construction and relies on data provided - by the OEDB. Currently, only members of the openego project team have access - to this database. +.. note:: Note, the data source of eGo relies on + the Open Energy Database. - The registration for the public + accessible API can be found on + `openenergy-platform.org/login `_. """ import pandas as pd @@ -38,147 +38,17 @@ "Europa-Universität Flensburg, " "Centre for Sustainable Energy Systems") __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolf_bunke,maltesc" +__author__ = "wolf_bunke, maltesc" if __name__ == '__main__': - # import scenario settings **args of eTraGo + # import scenario settings **args of eTraGo logger.info('Start calculation') ego = eGo(jsonpath='scenario_setting.json') ego.etrago_line_loading() - - -""" - - # add country code to bus and geometry (shapely) - # eTraGo.buses = eTraGo.buses.drop(['country_code','geometry'], axis=1) - # test = geolocation_buses(network = eTraGo, session) - - # get eTraGo results form db - if args['global']['recover']: - # TODO add it to class - eTraGo = etrago_from_oedb(session, args) - - # use eTraGo results from ego calculations if true - # ToDo make function edisgo_direct_specs() - - if args['eDisGo']['direct_specs']: - # ToDo: add this to utilities.py - - logger.info('Retrieving Specs') - - bus_id = 25402 # 23971 - - from ego.tools.specs import get_etragospecs_direct, get_mvgrid_from_bus_id - from egoio.db_tables import model_draft - specs = get_etragospecs_direct(session, bus_id, eTraGo, args) - - # ToDo make loop for all bus ids - # make function which links bus_id (subst_id) - if args['eDisGo']['specs']: - - logger.info('Retrieving Specs') - # ToDo make it more generic - # ToDo iteration of grids - # ToDo move part as function to utilities or specs - bus_id = 25402 # 27574 # 23971 - result_id = args['global']['result_id'] - - from ego.tools.specs import get_etragospecs_from_db, get_mvgrid_from_bus_id - from egoio.db_tables import model_draft - specs = get_etragospecs_from_db(session, bus_id, result_id) - - # This function can be used to call the correct MV grid - mv_grid = get_mvgrid_from_bus_id(session, bus_id) - - if args['global']['eDisGo']: - - logger.info('Starting eDisGo') - - # ToDo move part as function to utilities or specs - from datetime import datetime - from edisgo.grid.network import (Network, Scenario, - TimeSeries, Results, ETraGoSpecs) - import networkx as nx - import matplotlib.pyplot as plt - - # ToDo get ding0 grids over db - # ToDo implemente iteration - file_path = 'data/ding0_grids/ding0_grids__1802.pkl' - - #mv_grid = open(file_path) - - mv_grid_id = file_path.split('_')[-1].split('.')[0] - # Where retrieve from? Database or specs? - power_flow = (datetime(2011, 5, 26, 12), datetime(2011, 5, 26, 13)) - - timeindex = pd.date_range(power_flow[0], power_flow[1], freq='H') - - scenario = Scenario(etrago_specs=specs, - power_flow=(), - mv_grid_id=mv_grid_id, - scenario_name=args['eTraGo']['scn_name']) - - network = Network.import_from_ding0(file_path, - id=mv_grid_id, - scenario=scenario) - # check SQ MV grid - network.analyze() - - network.results.v_res( # nodes=network.mv_grid.graph.nodes(), - level='mv') - network.results.s_res() - - # A status quo grid (without new renewable gens) should not need reinforcement - network.reinforce() - - nx.draw(network.mv_grid.graph) - plt.draw() - plt.show() - - # network.results = Results() - costs = network.results.grid_expansion_costs - print(costs) - - # make interactive plot with folium - #logger.info('Starting interactive plot') - # igeoplot(network=eTraGo, session=session, args=args) # ToDo: add eDisGo results - - # calculate power plant dispatch without grid utilization (either in pypsa or in renpassgis) - - # result queries...call functions from utilities - - # total system costs of transmission grid vs. total system costs of all distribution grids results in overall total - # details on total system costs: - # existing plants: usage, costs for each technology - # newly installed plants (storages, grid measures) with size, location, usage, costs - # grid losses: amount and costs - - # possible aggregation of results - - # exports: total system costs, plots, csv export files - -""" -""" -# Using graphviz for Calculation Dokumentation. - -from pycallgraph import PyCallGraph -from pycallgraph.output import GraphvizOutput - -def main(): - graphviz = GraphvizOutput() - graphviz.output_file = 'basic.png' - - with PyCallGraph(output=graphviz): - logger.info('Start calculation') - - ego = eGo(jsonpath='scenario_setting.json') - - print(ego.etrago.storage_charges) - ego.etrago_network.plot() - -if __name__ == '__main__': - main() -""" + print(ego.etrago.generator) + print(ego.etrago.storage_charges) + print(ego.etrago.storage_costs) + print(ego.etrago.operating_costs) From aecca762098c9dd10ed205b9dcb3a4654f8223d0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 09:35:36 +0200 Subject: [PATCH 192/314] clean file --- doc/developer.rst | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/doc/developer.rst b/doc/developer.rst index 331756dc..2603815f 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -55,41 +55,3 @@ Change of units from Mega to kilo: :file: storage_units.csv :delim: , :header-rows: 1 - - -Testing zone -============ - - -ref pandas ----------- - -:ref:`apply ` -:ref:`apply ` -:ref:`apply ` -:ref:`apply ` -:ref:`apply ` -:ref:`apply ` - -meth pandas ------------ - -:meth:`apply ` -:meth:`pandas:pandas.dataframe.apply` -:meth:`pandas.dataframe.apply` - - -Test etrago ------------ - -:meth:`apply ` -:meth:`etrago:etrago.appl.etrago` -:meth:`etrago.appl.etrago` - -ref etrago ----------- - -:ref:`etrago ` -:ref:`etrago ` - -The :meth:`etrago() method ` creates your ``network``. From 021f4d4cc75e4eec87281f4d3926bcc57de76699 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 09:36:10 +0200 Subject: [PATCH 193/314] update file --- doc/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index f7011cc7..f11953f3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,14 +9,14 @@ Welcome to eGo documentation! .. note:: Note, this software is under construction and not ready for a normal use. -.. note:: Note, currently the data source of eGo relies on +.. note:: Note, the data source of eGo relies on the Open Energy Database. - The registration for the public accessible API can be found on `openenergy-platform.org/login `_. .. toctree:: - :maxdepth: 3 + :maxdepth: 2 welcome installation From f47fef37c92ad6c8dbbfa3a3c5379625c7735afe Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 09:36:55 +0200 Subject: [PATCH 194/314] add header eGo --- doc/welcome.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/welcome.rst b/doc/welcome.rst index 71449a54..41fa38b8 100644 --- a/doc/welcome.rst +++ b/doc/welcome.rst @@ -2,6 +2,9 @@ The eGo tool ============ +eGo +=== + The python package eGo is a toolbox and application which connects the tool eTraGo with a Optimization of flexibility options for transmission grids based on PyPSA and eDisGo which analysis and optimization distribution grids. All those python @@ -57,4 +60,3 @@ more details. You should have received a copy of the GNU General Public License along with this program. If not, see `www.gnu.org/licenses `_. - From b57e58a88e65c6dc9db0ede961398d49bfdffc05 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 09:37:51 +0200 Subject: [PATCH 195/314] update file --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index f11953f3..3a0e9dd3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -16,7 +16,7 @@ Welcome to eGo documentation! .. toctree:: - :maxdepth: 2 + :maxdepth: 1 welcome installation From 21b40095840dabab75195e791da9a1f569f4579b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 09:39:56 +0200 Subject: [PATCH 196/314] update file --- doc/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 3a0e9dd3..48a39518 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -21,7 +21,6 @@ Welcome to eGo documentation! welcome installation getting_started - usage_details theoretical_background developer whatsnew From 8f028e7544752909dc54b5fbbb7a7664c3c03450 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 09:42:07 +0200 Subject: [PATCH 197/314] removed text parts --- doc/developer.rst | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/doc/developer.rst b/doc/developer.rst index 2603815f..e056b669 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -3,6 +3,51 @@ Developer notes =============== +Installation +============ + +.. note:: + Installation is only tested on (Ubuntu like) linux OS. + +1. Create a virtualenvironment (where you like it) and activate it: + + ``$virtualenv --clear -p python3.5 ego_dev`` and ``$ cd ego_dev/`` + followed by ``$ source bin/activate`` + + +2. Clone eGo from github.com by running following command in your terminal: + + ``` + git clone https://github.com/openego/eGo + ``` + +With your activated environment `cd` to the cloned directory and run +``pip3 install -e eGo --process-dependency-links --allow-all-external`` . This will install all needed packages into your environment. + +.. warning:: + + Note, that the first release for deveolper is partly dependent on + forks and developent versions which could not automaticly be installed. + Check your installed packages using ``pip3 freeze`` with the + `ego_dependencies.txt `_ + + +3. Temporary solution: + +After your installation install the eGo PyPSA fork on `dev `_ +``pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA`` +and Folium for an web based ploting with +``pip3 install -e git+git@github.com:python-visualization/folium.git@5739244acb9868d001032df288500a047b232857#egg=folium`` + +Check if the `config.json `_ +file from eTraGo is installed in your libary ``/lib/python3.5/site-packages/etrago/tools`` . +If not copy and paste this file into this folder. + +If Database connection or table erros appears use: ``pip3 install -e git+git@github.com:openego/ego.io.git@3b76dfddea14d67eb4421b6223bf981d8851e4e6#egg=ego.io`` + + + + From a748c90918c882ed0369cbec55fa8605a229ca00 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 09:54:00 +0200 Subject: [PATCH 198/314] update file --- doc/getting_started.rst | 62 +++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/doc/getting_started.rst b/doc/getting_started.rst index b00b5c20..4629ee76 100644 --- a/doc/getting_started.rst +++ b/doc/getting_started.rst @@ -2,57 +2,41 @@ Getting started =============== -.. warning:: - Note, eGo, eTraGo and eDisGo relies on data provided by the OEDB. Currently, only members - of the openego project team have access to this database. Public access - (SQL queries wrapped by HTML) to the OEDB will be provided soon - - -Installation -============ - -.. note:: - Installation is only tested on (Ubuntu like) linux OS. - -1. Create a virtualenvironment (where you like it) and activate it: +How to use eGo? +=============== - ``$virtualenv --clear -p python3.5 ego_dev`` and ``$ cd ego_dev/`` - followed by ``$ source bin/activate`` +1. Check and prepare your eGo setting in ``ego/scenario_setting.json`` +2. Start your calculation with predefined results tools and run under + ``eGo/ego`` the main file with ``>>> python3 ego_main.py`` -2. Clone eGo from github.com by running following command in your terminal: +.. code-block:: bash - ``` - git clone https://github.com/openego/eGo - ``` + >>> python3 ego_main.py + >>> ... + >>> INFO:ego:Start calculation + >>> ... -With your activated environment `cd` to the cloned directory and run -``pip3 install -e eGo --process-dependency-links --allow-all-external`` . This will install all needed packages into your environment. -.. warning:: +Examples +======== - Note, that the first release for deveolper is partly dependent on - forks and developent versions which could not automaticly be installed. - Check your installed packages using ``pip3 freeze`` with the - `ego_dependencies.txt `_ +.. code-block:: python -3. Temporary solution: + # import the eGo tool + from ego.tools.io import eGo - After your installation install the eGo PyPSA fork on `dev `_ - ``pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA`` - and Folium for an web based ploting with - ``pip3 install -e git+git@github.com:python-visualization/folium.git@5739244acb9868d001032df288500a047b232857#egg=folium`` + # Run your scenario + ego = eGo(jsonpath='scenario_setting.json') - Check if the `config.json `_ - file from eTraGo is installed in your libary ``/lib/python3.5/site-packages/etrago/tools`` . - If not copy and paste this file into this folder. + # Analyse your results on extra high voltage level (etrago) + ego.etrago_line_loading() - If Database connection or table erros appears use: ``pip3 install -e git+git@github.com:openego/ego.io.git@3b76dfddea14d67eb4421b6223bf981d8851e4e6#egg=ego.io`` +Reesult Examples k=30 Cluster Plot of Germany +============================================= -Using eGo: -========== -1. check and prepare your eGo setting in ``ego/scenario_setting.json`` -2. Start your calculation with in the directory of ``eGo/ego`` with ``python3 ego_main.py`` +.. raw:: html + :file: images/iplot_k30_cluster.html From f1aa6ebd8823358400866dbb104edc13b3181a74 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 09:59:37 +0200 Subject: [PATCH 199/314] update file --- doc/developer.rst | 64 +++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/doc/developer.rst b/doc/developer.rst index e056b669..39e135e0 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -11,67 +11,52 @@ Installation 1. Create a virtualenvironment (where you like it) and activate it: - ``$virtualenv --clear -p python3.5 ego_dev`` and ``$ cd ego_dev/`` - followed by ``$ source bin/activate`` +.. code-block:: bash + + $ virtualenv --clear -p python3.5 ego_dev`` + $ cd ego_dev/ + $ source bin/activate 2. Clone eGo from github.com by running following command in your terminal: - ``` - git clone https://github.com/openego/eGo - ``` +.. code-block:: bash + + $ git clone https://github.com/openego/eGo + With your activated environment `cd` to the cloned directory and run -``pip3 install -e eGo --process-dependency-links --allow-all-external`` . This will install all needed packages into your environment. +``pip3 install -e eGo --process-dependency-links --allow-all-external`` . +This will install all needed packages into your environment. .. warning:: Note, that the first release for deveolper is partly dependent on forks and developent versions which could not automaticly be installed. Check your installed packages using ``pip3 freeze`` with the - `ego_dependencies.txt `_ + `ego_dependencies.txt + `_ -3. Temporary solution: +3. Work arounds : -After your installation install the eGo PyPSA fork on `dev `_ +After your installation install the eGo PyPSA fork on +`dev `_ ``pip3 install -e git+https://github.com/openego/PyPSA.git@dev#egg=PyPSA`` and Folium for an web based ploting with -``pip3 install -e git+git@github.com:python-visualization/folium.git@5739244acb9868d001032df288500a047b232857#egg=folium`` +``pip3 install -e git+git@github.com:python-visualization/folium.git@dev#egg=folium`` Check if the `config.json `_ -file from eTraGo is installed in your libary ``/lib/python3.5/site-packages/etrago/tools`` . +file from eTraGo is installed in your libary +``/lib/python3.5/site-packages/etrago/tools`` . If not copy and paste this file into this folder. -If Database connection or table erros appears use: ``pip3 install -e git+git@github.com:openego/ego.io.git@3b76dfddea14d67eb4421b6223bf981d8851e4e6#egg=ego.io`` - - - - +If Database connection or table erros appears use: +``pip3 install -e git+git@github.com:openego/ego.io.git@dev#egg=ego.io`` - - -Interface eDisGo for grid and storage costs -=========================================== - - -.. code-block:: python - - # get setting from eTraGo for eDisGo - specs = get_etragospecs_from_db(session, bus_id, result_id, scn_name) - ... - # Create scenario or eDisGo of one mv Grid - scenario = Scenario(etrago_specs=specs, - power_flow=(), - mv_grid_id=mv_grid_id, - scenario_name='NEP 2035') - ... - # import ding0 mv grid - network = Network.import_from_ding0(file_path, - id=mv_grid_id, - scenario=scenario) - +eDisGo +====== eDisGo units ------------ @@ -100,3 +85,6 @@ Change of units from Mega to kilo: :file: storage_units.csv :delim: , :header-rows: 1 + +eTraGo +====== From c0a5930639c3d7e602873522e579723f7b30837a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 10:00:48 +0200 Subject: [PATCH 200/314] update file --- doc/usage_details.rst | 11 ----------- ego/tools/io.py | 12 ++++++++++++ 2 files changed, 12 insertions(+), 11 deletions(-) delete mode 100644 doc/usage_details.rst diff --git a/doc/usage_details.rst b/doc/usage_details.rst deleted file mode 100644 index 84ad885e..00000000 --- a/doc/usage_details.rst +++ /dev/null @@ -1,11 +0,0 @@ -=============== -How to use eGo? -=============== - - -Examples -======== - -1. Change your json file in order to select your calculation settings. - -2. Run the main file with ``$ python3 ego_main.py`` diff --git a/ego/tools/io.py b/ego/tools/io.py index 14825c32..5a3e1865 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -118,6 +118,15 @@ class eTraGoResults(egoBasic): of eTraGo and it's network container for eGo. + + Returns + ------- + network_etrago: :meth:`etrago.appl.etrago` + eTraGo network object + + + + Examples -------- @@ -125,8 +134,11 @@ class eTraGoResults(egoBasic): See also -------- + The `eTraGo`_ documentation. + + References ---------- .. _eTraGo: From edb745e099b3e654f20496c880535ae210f8ecba Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 10:32:09 +0200 Subject: [PATCH 201/314] update files --- doc/getting_started.rst | 6 +- doc/images/iplot_cluster.html | 266 ++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+), 3 deletions(-) create mode 100644 doc/images/iplot_cluster.html diff --git a/doc/getting_started.rst b/doc/getting_started.rst index 4629ee76..84560d64 100644 --- a/doc/getting_started.rst +++ b/doc/getting_started.rst @@ -34,9 +34,9 @@ Examples ego.etrago_line_loading() -Reesult Examples k=30 Cluster Plot of Germany -============================================= +Example Cluster of Germany +========================== .. raw:: html - :file: images/iplot_k30_cluster.html + :file: images/iplot_cluster.html diff --git a/doc/images/iplot_cluster.html b/doc/images/iplot_cluster.html new file mode 100644 index 00000000..2beb752c --- /dev/null +++ b/doc/images/iplot_cluster.html @@ -0,0 +1,266 @@ + + + + + + Cluster Example open_eGo + + + + + + + + + + + + + + + + + + +

+ + + + + + From a854c3515e55f07b99f29d718c9163764484b904 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 10:34:54 +0200 Subject: [PATCH 202/314] remove file --- doc/images/iplot_cluster.html | 266 ---------------------------------- 1 file changed, 266 deletions(-) delete mode 100644 doc/images/iplot_cluster.html diff --git a/doc/images/iplot_cluster.html b/doc/images/iplot_cluster.html deleted file mode 100644 index 2beb752c..00000000 --- a/doc/images/iplot_cluster.html +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - Cluster Example open_eGo - - - - - - - - - - - - - - - - - - -
-
-
-
-
- - - - - - - -
- -
-
-
-
-
- -
-
-
-
+ - -
-
-
- -
- -
-
-
Leaflet | WDB Media
-
-
-
- - - - - - From 9b21bea49215b04c0fe586accebf2a798b6f1a1b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 10:39:11 +0200 Subject: [PATCH 203/314] update file --- ego/ego_main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 69d84603..468837f2 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -31,8 +31,9 @@ import os from ego.tools.utilities import define_logging logger = define_logging(log_name='ego.log') -# if not 'READTHEDOCS' in os.environ: -from ego.tools.io import eGo + +if not 'READTHEDOCS' in os.environ: + from ego.tools.io import eGo __copyright__ = ("Flensburg University of Applied Sciences, " "Europa-Universität Flensburg, " From 7982ffe70d9e21c7c6d212b92a58c77c7bdba701 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 10:47:32 +0200 Subject: [PATCH 204/314] update format --- doc/index.rst | 2 +- doc/whatsnew/v0-2-0.rst | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 48a39518..3eb4119b 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -16,7 +16,7 @@ Welcome to eGo documentation! .. toctree:: - :maxdepth: 1 + :maxdepth: 2 welcome installation diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index 212e6282..d8db7b49 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -5,9 +5,9 @@ Second release of the eGo application. New features have been included in this release. Major changes being the new class structure and separation of methods into the given file structure. -Moreover the use of the Dataprocessing version 'v0.4.1' and 'v0.4.2' is +Moreover the use of the Dataprocessing version ``'v0.4.1' ``and ``'v0.4.2'`` is integrate. For eGo and the integration and interaction the app will depend on a -data version >= 'v0.4.1' in order to ensure the correct data handling. +data version ``>= 'v0.4.1'`` in order to ensure the correct data handling. Furthermore the inclusion of new methods and classes for eDisGo, storages etc. is done. @@ -20,10 +20,12 @@ Added features * Cleaned and restructured eGo classes and functions - Moved classes of eGo from results.py to io.py - Move serveral function - - Introduce new files for edisgo handling: - - edisgo_integration.py - - mv_cluster.py - - Introduce new file storages.py for eTraGo + +* Introduce new files for edisgo handling + - edisgo_integration.py + - mv_cluster.py + +* Introduce new file storages.py for eTraGo * Updated eTraGo 0.6 and integrated eTraGo's new functions and features to eGo * Updated eDisGo 0.0.3 version which includes the features of a parallelization for custom function and other important API changes. From f773e53be66a72925871904e84245311c55ad85a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 11:53:29 +0200 Subject: [PATCH 205/314] update doc strings --- ego/tools/io.py | 71 +++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 5a3e1865..06144653 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -79,10 +79,10 @@ class egoBasic(object): Returns ------- - eTraGo : :pandas:`pandas.Dataframe` of PyPSA - Network container of eTraGo based on PyPSA - eDisGo : :pandas:`pandas.Dataframe` of PyPSA - Network container of eDisGo based on PyPSA + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` + network_edisgo : :pandas:`pandas.Dataframe` + Network container of eDisGo json_file : :obj:dict Dictionary of the ``scenario_setting.json`` file session : :sqlalchemy:`sqlalchemy.orm.session.Session` @@ -117,15 +117,12 @@ class eTraGoResults(egoBasic): """The ``eTraGoResults`` class create and contains all results of eTraGo and it's network container for eGo. - - Returns ------- - network_etrago: :meth:`etrago.appl.etrago` - eTraGo network object - - - + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` + etrago: :pandas:`pandas.Dataframe` + eTraGo results Examples -------- @@ -298,12 +295,6 @@ class eDisGoResults(eTraGoResults): """ eDisGo Results This module contains all results of eDisGo for eGo. - - ToDo - ---- - - add eDisGo - - add iteration for multiple ding0 grids - """ def __init__(self, jsonpath, *args, **kwargs): @@ -328,15 +319,18 @@ class eGo(eDisGoResults): """Main eGo module which including all results and main functionalities. - Parameters - ---------- - eTraGo : Network + Returns + ------- + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` + network_edisgo : :pandas:`pandas.Dataframe` + Network container of eDisGo + edisgo : :pandas:`pandas.Dataframe` + aggregated results of eDisGo + etrago : :pandas:`pandas.Dataframe` + aggregated results of eTraGo - eDisGo : Network - ToDo - ---- - - add eDisGo """ def __init__(self, jsonpath, *args, **kwargs): @@ -370,16 +364,13 @@ def geolocation_buses(network, session): Parameters ---------- - network : Network - eTraGo Network + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` session : :sqlalchemy:`sqlalchemy.orm.session.Session` SQLAlchemy session to the OEDB - ToDo - ---- - - check eTrago stack generation plots and other in order of adaptation - """ + # ToDo: check eTrago stack generation plots and other in order of adaptation # Start db connetion # get renpassG!S scenario data @@ -435,7 +426,6 @@ def geolocation_buses(network, session): def results_to_excel(ego): """ Wirte results to excel - """ # Write the results as xlsx file # ToDo add time of calculation to file name @@ -455,8 +445,8 @@ def results_to_excel(ego): def etrago_from_oedb(session, json_file): - """ - Function with import eTraGo results for the Database. + """Function which import eTraGo results for the Database by + ``result_id`` and if ``recover`` is set to ``true``. Parameters ---------- @@ -467,12 +457,9 @@ def etrago_from_oedb(session, json_file): Returns ------- - network : + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` - ToDo - ---- - add Mapping for grid schema - make it more generic -> class? """ result_id = json_file['global']['result_id'] @@ -542,13 +529,11 @@ def series_results(name, column, session, result_id, ormclass): ---------- session: : sqlalchemy: `sqlalchemy.orm.session.Session < orm/session_basics.html >` SQLAlchemy session to the OEDB - - ToDo - ---- - - check index of bus_t and soon is wrong! - """ + + # TODO - check index of bus_t and soon is wrong! # TODO: pls make more robust + id_column = re.findall(r'[A-Z][^A-Z]*', name)[0] + '_' + 'id' id_column = id_column.lower() From 0ccd620513230c1fb3c996796147dcf2777f1d56 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 11:59:31 +0200 Subject: [PATCH 206/314] update doc strings --- ego/tools/economics.py | 81 ++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index e4bad419..1c332c66 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -19,10 +19,6 @@ # File description """This module collects useful functions for economic calculation of eGo which can mainly distinguished in operational and investment costs. - -Todo: - 1) Investment costs of eTrago and eDisGo - 2) Total system costs """ import io @@ -40,11 +36,11 @@ __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" __author__ = "wolfbunke" -# calculate annuity per time step or periode +# calculate annuity per time step or periode +def annuity_per_period(capex, n, wacc, t, p): + """ Calculate per given period -def annuity_per_period(capex, n, wacc, t): - """ Parameters ---------- capex : float @@ -53,21 +49,18 @@ def annuity_per_period(capex, n, wacc, t): Number of years that the investment is used (economic lifetime) wacc : float Weighted average cost of capital - - ToDo - ---- t : int Timesteps in hours - i : float + p : float interest rate - ... + """ # ToDo change formular to hourly annuity costs return capex * (wacc * (1 + wacc) ** n) / ((1 + wacc) ** n - 1) -def edisgo_convert_capital_costs(): +def edisgo_convert_capital_costs(grid_components, json_file): """ Parameters @@ -78,8 +71,19 @@ def edisgo_convert_capital_costs(): (Name, investment_cost, lifetime) json_file : :obj:dict Dictionary of the ``scenario_setting.json`` file + _start_snapshot : int + Start point of calculation from ``scenario_setting.json`` file + _end_snapshot : int + End point of calculation from ``scenario_setting.json`` file + _p : numeric + interest rate of investment + _T : int + lifetime of investment - + Returns + ------- + capital_cost : + calculated capital costs of components """ # eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 @@ -87,14 +91,16 @@ def edisgo_convert_capital_costs(): # p=0.05, T=40): # Define function + pass + def etrago_operating_costs(network): """ Function to get all operating costs of eTraGo. Parameters ---------- - network : Network of eTraGo - Network of eTraGo + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` Returns ------- @@ -107,12 +113,10 @@ def etrago_operating_costs(network): - grid losses : amount and costs - use calc_line_losses(network) from etrago pf_post_lopf - ToDo - ---- - - change naming and function structure - - seperate operation costs in other functions ? - """ + # TODO - change naming and function structure + # TODO - seperate operation costs in other functions ? + etg = network #etg = eTraGo # groupby v_nom @@ -152,8 +156,8 @@ def etrago_grid_investment(network, json_file): Parameters ---------- - network : Network - eTraGo + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` json_file : :obj:dict Dictionary of the ``scenario_setting.json`` file @@ -219,13 +223,18 @@ def etrago_grid_investment(network, json_file): pass -def edisgo_grid_investment(network): +def edisgo_grid_investment(network_edisgo): """Function to get all costs of grid investment of eDisGo. - Notes - ----- - - ToDo add iteration and container of all costs of edisgo network + Parameters + ---------- + + network_edisgo : :pandas:`pandas.Dataframe` + Network container of eDisGo + + """ + pass @@ -233,13 +242,10 @@ def get_generator_investment(network, scn_name): """ Get investment costs per carrier/gernator. work around later db table -> check capital_cost as cost input?!? - - ToDo - ---- - - change values in csv - - add values to database - """ + # TODO - change values in csv + # - add values to database + etg = network path = os.getcwd() @@ -268,8 +274,7 @@ def get_generator_investment(network, scn_name): def investment_costs(network): - """ - Return pandas DataFrame with investment costs of + """Return pandas DataFrame with investment costs of etrago: Storages @@ -279,11 +284,9 @@ def investment_costs(network): Line extentation Storage costs? - ToDo - ---- - - add edisgo - """ + # TODO add edisgo + etg = network invest = pd.DataFrame() From 1673375da4431b738a7546379b9ed56d1a8d75d0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 12:11:54 +0200 Subject: [PATCH 207/314] update doc strings --- ego/tools/plots.py | 48 +++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/ego/tools/plots.py b/ego/tools/plots.py index 6fbed535..8bed1278 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -19,11 +19,9 @@ # File description """Module which collects useful functions for plotting eTraGo, eDisGo and eGo results. - -ToDo ----- -- Implement plotly for iplot """ +# TODO - Implement plotly for iplot + import numpy as np import pandas as pd import os @@ -92,6 +90,15 @@ def carriers_colore(): def make_all_plots(network): """ Test function which run all ploting functions. + Parameters + ---------- + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` + + Returns + ------- + plots : :meth:`matplotlib.pyplot` + Returns plots """ # make a line loading plot plot_line_loading(network) @@ -120,27 +127,26 @@ def igeoplot(network, session, tiles=None, geoloc=None, args=None): Parameters ---------- - network : PyPSA - PyPSA network container + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` tiles : str Folium background map style `None` as OSM or `Nasa` - geoloc : list of str - Define center of map as (lon,lat) + geoloc : :obj:list + List which define center of map as (lon,lat) Returns ------- plot : html - HTML file this .js plot - - ToDo - ---- - - implement eDisGo Polygons - - fix version problems of data - - use grid.ego_dp_hvmv_substation subst_id and otg_id - - use cluster or boxes to limit data volumn - - add Legend - - Map see: http://nbviewer.jupyter.org/gist/BibMartin/f153aa957ddc5fadc64929abdee9ff2e + HTML file with .js plot """ + # TODO + # - implement eDisGo Polygons + # - fix version problems of data + # - use grid.ego_dp_hvmv_substation subst_id and otg_id + # - use cluster or boxes to limit data volumn + # - add Legend + # - Map see: http://nbviewer.jupyter.org/gist/BibMartin/f153aa957ddc5fadc64929abdee9ff2e + # - test cluster if geoloc is None: geoloc = [network.buses.y.mean(), network.buses.x.mean()] @@ -293,6 +299,8 @@ def colormaper(): def prepareGD(session, subst_id=None, version=None): + """ + """ if version == 'v0.2.11': query = session.query(EgoDpMvGriddistrict.subst_id, @@ -316,7 +324,7 @@ def prepareGD(session, subst_id=None, version=None): return region -def total_power_costs_plot(eTraGo): +def total_power_costs_plot(etrago_network): """ plot power price of eTraGo @@ -327,7 +335,7 @@ def total_power_costs_plot(eTraGo): Returns ------- plot :obj:`matplotlib.pyplot.show` - Date: Fri, 13 Jul 2018 12:15:46 +0200 Subject: [PATCH 208/314] update doc string --- ego/tools/results.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/ego/tools/results.py b/ego/tools/results.py index 63bf772d..e5b083db 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -19,11 +19,8 @@ # File description """This module include the results functions for analyze and creating results based on eTraGo or eDisGo for eGo. - -ToDo ----- - - write results to database """ +# TODO - write results to database import io import os @@ -48,17 +45,17 @@ def create_etrago_results(network, scn_name): # rename function Parameters ---------- network : :class:`~.etrago.tools.io.NetworkScenario` - eTraGo ``NetworkScenario`` based on PyPSA Network. See also: + eTraGo ``NetworkScenario`` based on PyPSA Network. See also `pypsa.network `_ scn_name : str Name of used scenario - Results + Returns ------- - etrago : :pandas:`pandas.DataFrame` - Results as DataFrame. + generator : :pandas:`pandas.DataFrame` + Result of generator as DataFrame in ``ego.etrago.generator`` """ @@ -105,19 +102,20 @@ def results_per_voltage(network): Parameters ---------- network : :class:`etrago.tools.io.NetworkScenario` - eTraGo ``NetworkScenario`` based on PyPSA Network. See also: + eTraGo ``NetworkScenario`` based on PyPSA Network. See also `pypsa.network `_ - Results + Returns ------- """ def ego_results_to_oedb(total): - """ ToDo: Function to upload results into oedb database + """ Function to upload results into oedb database """ + # TODO pass From d093c51dda3ace624bbfca4f099606d69dbd6846 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 12:16:25 +0200 Subject: [PATCH 209/314] update doc string --- ego/tools/storages.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 0cae1ac3..88b47725 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -42,7 +42,7 @@ def total_storage_charges(network): Parameters ---------- network : :etrago:`etrago.tools.io.NetworkScenario` - eTraGo ``NetworkScenario`` based on PyPSA Network. See also: + eTraGo ``NetworkScenario`` based on PyPSA Network. See also `pypsa.network `_ Results @@ -105,7 +105,7 @@ def etrago_storages(network): Parameters ---------- network : :class:`~.etrago.tools.io.NetworkScenario` - eTraGo ``NetworkScenario`` based on PyPSA Network. See also: + eTraGo ``NetworkScenario`` based on PyPSA Network. See also `pypsa.network `_ Returns From 7d40d2c1b055c0bd5d0dc26500bc63296bf0df7a Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 12:19:03 +0200 Subject: [PATCH 210/314] update doc strings --- ego/tools/utilities.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index 767bac62..b6342d80 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -40,7 +40,7 @@ def define_logging(log_name='ego.log'): Name of log file. Default: ``ego.log``. - Results + Returns ------- ego_logger : :class:`logging.basicConfig`. Set up ``ego_logger`` object of package ``logging`` @@ -76,7 +76,7 @@ def define_logging(log_name='ego.log'): # import scenario settings **args -def get_scenario_setting(json_file='scenario_setting.json'): +def get_scenario_setting(jsonpath='scenario_setting.json'): """Get and open json file with scenaio settings of eGo. The settings incluede global, eTraGo and eDisGo specific settings of arguments and parameters for a reproducible @@ -88,38 +88,38 @@ def get_scenario_setting(json_file='scenario_setting.json'): Default: ``scenario_setting.json`` Name of scenario setting json file - Results + Returns ------- - scn_set : dict + json_file : dict Dictionary of json file """ path = os.getcwd() # add try ego/ print("Your path is:\n", path) - with open(path + '/'+json_file) as f: - scn_set = json.load(f) + with open(path + '/'+jsonpath) as f: + json_file = json.load(f) - if scn_set['global'].get('eTraGo') == True: + if json_file['global'].get('eTraGo') == True: print('Using and importing eTraGo settings') # special case of SH and model_draft # ToDo: check and maybe remove this part sh_scen = ["SH Status Quo", "SH NEP 2035", "SH eGo 100"] - if scn_set['eTraGo'].get('scn_name') in sh_scen and scn_set['eTraGo'].\ + if json_file['eTraGo'].get('scn_name') in sh_scen and json_file['eTraGo'].\ get('gridversion') == "v0.4.2": - scn_set['eTraGo']['gridversion'] = None + json_file['eTraGo']['gridversion'] = None # add global parameter to eTraGo scn_set - scn_set['eTraGo'].update({'db': scn_set['global'].get('db')}) - scn_set['eTraGo'].update( - {'gridversion': scn_set['global'].get('gridversion')}) + json_file['eTraGo'].update({'db': json_file['global'].get('db')}) + json_file['eTraGo'].update( + {'gridversion': json_file['global'].get('gridversion')}) - if scn_set['global'].get('eDisGo') == True: + if json_file['global'].get('eDisGo') == True: print('Use eDisGo settings') - return scn_set + return json_file def get_time_steps(json_file): From 7d7f2f75ac1cdb3e669feb8a22273ad2195975ad Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 12:24:27 +0200 Subject: [PATCH 211/314] update doc strings --- ego/tools/storages.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 88b47725..cb64ab91 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -45,7 +45,7 @@ def total_storage_charges(network): eTraGo ``NetworkScenario`` based on PyPSA Network. See also `pypsa.network `_ - Results + Returns ------- results : :pandas:`pandas.DataFrame` Summarize and returns a ``DataFrame`` of the storages optimaziation. From ef41f4465807ae6faf8b587d3fc4631ab6575423 Mon Sep 17 00:00:00 2001 From: maltesc Date: Fri, 13 Jul 2018 13:43:51 +0200 Subject: [PATCH 212/314] gen import test --- ego/scenario_setting.json | 6 ++-- ego/tools/edisgo_integration.py | 54 ++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 40910725..c4ccb788 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -38,8 +38,10 @@ }, "eDisGo": { "specs": true, - "ding0_files": "data/MV_grids/20180712120156", - "mv_cluster": null, + "ding0_files": "data/MV_grids/20180713110719", + "choice_mode": "manual", + "no_grids": null, + "manual_grids": [1729, 1730], "scn_name": "NEP 2035", "comments": "make a comment" } diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index d90101b3..305427c3 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -29,6 +29,7 @@ from ego.tools.mv_cluster import ( analyze_attributes, cluster_mv_grids) +from ego.tools.utilities import define_logging ## Other Packages import os @@ -39,7 +40,7 @@ # Logging logging.basicConfig(format='%(asctime)s %(message)s',level=logging.INFO) -logger = logging.getLogger(__name__) +logger = logging.getLogger('ego') class EDisGoNetworks: @@ -61,8 +62,8 @@ def __init__(self, **kwargs): ### eDisGo args self._edisgo_args = self._json_file['eDisGo'] self._ding0_files = self._edisgo_args['ding0_files'] - self._mv_cluster = self._edisgo_args['mv_cluster'] - + self._choice_mode = self._edisgo_args['choice_mode'] + self._scn_name = self._edisgo_args['scn_name'] if self._scn_name == 'Status Quo': self._generator_scn = None @@ -91,7 +92,7 @@ def analyze_cluster_attributes(self): """ analyze_attributes(self._ding0_files) - def cluster_mv_grids(self): + def cluster_mv_grids(self, no_grids): """ Clusters the MV grids based on the attributes @@ -103,7 +104,7 @@ def cluster_mv_grids(self): logger.info('Attributes will be calculated') self.analyze_cluster_attributes() - return cluster_mv_grids(self._ding0_files, self._mv_cluster) + return cluster_mv_grids(self._ding0_files, no_grids) def check_available_mv_grids(self): @@ -119,10 +120,22 @@ def check_available_mv_grids(self): def grid_choice(self): - if self._mv_cluster: - logger.info('Clustering to {} MV grids'.format(self._mv_cluster)) - cluster = self.cluster_mv_grids() - else: + if self._choice_mode == 'cluster': + no_grids = self._edisgo_args['no_grids'] + logger.info('Clustering to {} MV grids'.format(no_grids)) + cluster = self.cluster_mv_grids(no_grids) + + elif self._choice_mode == 'manual': + man_grids = self._edisgo_args['manual_grids'] + cluster = pd.DataFrame( + man_grids, + columns=['the_selected_network_id']) + cluster['no_of_points_per_cluster'] = 1 + logger.info( + 'Calculating manually chosen MV grids {}'.format(man_grids) + ) + + elif self._choice_mode == 'all': mv_grids = self.check_available_mv_grids() cluster = pd.DataFrame( mv_grids, @@ -132,8 +145,12 @@ def grid_choice(self): logger.info( 'Calculating all available {} MV grids'.format(no_grids) ) + self._grid_choice = cluster + + + def run_edisgo_pool(self, parallelization=False): if parallelization is True: @@ -167,15 +184,15 @@ def run_edisgo_pool(self, parallelization=False): self._edisgo_grids[ mv_grid_id ] = self.run_edisgo(mv_grid_id) - except: + except Exception: self._edisgo_grids[mv_grid_id] = None - logger.info( - 'MV grid {} failed'.format(mv_grid_id) + logger.exception( + 'MV grid {} failed: \n'.format(mv_grid_id) + ) count += 1 - def run_edisgo(self, mv_grid_id, *args): """ Runs eDisGo with the desired settings. @@ -214,12 +231,13 @@ def run_edisgo(self, mv_grid_id, *args): logger.info('eTraGo feed-in case') edisgo_grid.network.results = Results() -# edisgo_grid.network.pypsa = None -# -# if self._generator_scn: -# edisgo_grid.import_generators( -# generator_scenario=self._generator_scn) + edisgo_grid.network.pypsa = None + + if self._generator_scn: + edisgo_grid.import_generators( + generator_scenario=self._generator_scn) logger.warning('No generators are imported') + edisgo_grid.network.pypsa = None edisgo_grid.network.timeseries = TimeSeriesControl( # Here, I use only normalized values from specs From 9928d45a161b04ecbdaea5dbce401ff3ea6321a7 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 13:56:31 +0200 Subject: [PATCH 213/314] update doc string --- ego/tools/storages.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index cb64ab91..8d5ec9a8 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -52,17 +52,15 @@ def total_storage_charges(network): Notes ----- + The ``results`` dataframe inclueds following parameters: charge : numeric Quantity of charged Energy in MWh over scenario time steps - discharge : numeric Quantity of discharged Energy in MWh over scenario time steps - count : int Number of storage units - p_nom_o_sum: numeric Sum of optimal installed power capacity """ From be67f7c2d7479c3b3fe6d17d84e5854cd564dc07 Mon Sep 17 00:00:00 2001 From: maltesc Date: Fri, 13 Jul 2018 14:54:56 +0200 Subject: [PATCH 214/314] first integration finished --- ego/tools/edisgo_integration.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 305427c3..ecb07aaa 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -231,14 +231,13 @@ def run_edisgo(self, mv_grid_id, *args): logger.info('eTraGo feed-in case') edisgo_grid.network.results = Results() - edisgo_grid.network.pypsa = None - - if self._generator_scn: - edisgo_grid.import_generators( - generator_scenario=self._generator_scn) - logger.warning('No generators are imported') - edisgo_grid.network.pypsa = None + +# Generator Import is currently not working in eDisGo +# if self._generator_scn: +# edisgo_grid.import_generators( +# generator_scenario=self._generator_scn) + print(specs['conv_dispatch']) edisgo_grid.network.timeseries = TimeSeriesControl( # Here, I use only normalized values from specs timeseries_generation_fluctuating=specs['potential'], @@ -247,9 +246,10 @@ def run_edisgo(self, mv_grid_id, *args): config_data=edisgo_grid.network.config, timeindex=specs['conv_dispatch'].index).timeseries - update_pypsa_timeseries( - edisgo_grid.network, - timesteps=specs['conv_dispatch'].index) +# This will be used after the next eDisGo release +# update_pypsa_timeseries( +# edisgo_grid.network, +# timesteps=specs['conv_dispatch'].index) logger.warning('Curtailment can only be included after gen import') # edisgo_grid.curtail(curtailment_methodology='curtail_all', @@ -257,10 +257,12 @@ def run_edisgo(self, mv_grid_id, *args): # timeseries_curtailment=specs['curtailment_abs']) # # # Think about the other curtailment functions!!!! - + +# This will become unnecessary with the next eDisGo release + edisgo_grid.network.pypsa = None edisgo_grid.analyze() - edisgo_grid.reinforce() + edisgo_grid.reinforce() # Get costs costs_grouped = \ @@ -273,7 +275,7 @@ def run_edisgo(self, mv_grid_id, *args): costs.rename(columns={'level_0': 'grid'}, inplace=True) # Grid issues besser verstehen!! Und evtl. mit aussgeben - + print(costs) return edisgo_grid From ae536e039302ea69e150ba6ffbe127489405a219 Mon Sep 17 00:00:00 2001 From: maltesc Date: Fri, 13 Jul 2018 15:37:54 +0200 Subject: [PATCH 215/314] first complete integration --- ego/tools/edisgo_integration.py | 36 +++++++++++++++++++++++---------- ego/tools/io.py | 4 ++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index ecb07aaa..a62edf3a 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -157,11 +157,11 @@ def run_edisgo_pool(self, parallelization=False): logger.info('Parallelization') raise NotImplementedError -# id_list = self._cluster['the_selected_network_id'].tolist() +# id_list = self._grid_choice['the_selected_network_id'].tolist() # # self._pool = run_edisgo_pool_flexible( # ding0_id_list=id_list, -# func=test_pool, +# func=EDisGoNetworks.run_edisgo, # func_arguments=['toll']) else: @@ -181,9 +181,16 @@ def run_edisgo_pool(self, parallelization=False): 'MV grid {}'.format(mv_grid_id) ) try: + bus_id = self.get_bus_id_from_mv_grid(mv_grid_id) self._edisgo_grids[ mv_grid_id - ] = self.run_edisgo(mv_grid_id) + ] = self.run_edisgo( + mv_grid_id=mv_grid_id, + bus_id=bus_id, + session=self._session, + etrago_network=self._etrago_network, + scn_name=self._scn_name, + ding0_files=self._ding0_files) except Exception: self._edisgo_grids[mv_grid_id] = None logger.exception( @@ -192,24 +199,31 @@ def run_edisgo_pool(self, parallelization=False): ) count += 1 - - def run_edisgo(self, mv_grid_id, *args): + + @staticmethod + def run_edisgo( + mv_grid_id, + bus_id, + session, + etrago_network, + scn_name, + ding0_files): + """ Runs eDisGo with the desired settings. """ logger.info('Calculating interface values') - bus_id = self.get_bus_id_from_mv_grid(mv_grid_id) - + specs = get_etragospecs_direct( - self._session, + session, bus_id, - self._etrago_network, - self._scn_name) + etrago_network, + scn_name) ding0_filepath = ( - self._ding0_files + ding0_files + '/ding0_grids__' + str(mv_grid_id) + '.pkl') diff --git a/ego/tools/io.py b/ego/tools/io.py index b3874284..93b0f8e2 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -311,6 +311,10 @@ def __init__(self, jsonpath, *args, **kwargs): self.edisgo_networks = EDisGoNetworks( json_file=self.json_file, etrago_network=self.etrago_network) + + def edisgo_total_costs(self, **kwargs): + + return df From b5c0a2eb79622ab7726c04ffc372eb852ef50a41 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 15:42:42 +0200 Subject: [PATCH 216/314] add comment --- ego/tools/io.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ego/tools/io.py b/ego/tools/io.py index 06144653..4d20674a 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -221,6 +221,7 @@ def etrago_line_loading(self, **kwargs): Integrate and use function from eTraGo. For more information see: """ + # add if time_step <1 -> plot return plot_line_loading(network=self.etrago_network, **kwargs) def etrago_stacked_gen(self, **kwargs): From fdb3d73215317375dcb7d4ab00f23f2382e0ade5 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 15:43:09 +0200 Subject: [PATCH 217/314] update file --- ego/ego_main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 468837f2..5334dae2 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -48,8 +48,9 @@ logger.info('Start calculation') ego = eGo(jsonpath='scenario_setting.json') + logger.info('Print results') ego.etrago_line_loading() print(ego.etrago.generator) - print(ego.etrago.storage_charges) + print(ego.etrago.grid_costs) print(ego.etrago.storage_costs) print(ego.etrago.operating_costs) From 5f2f576fd958992d7c15fad660b32643ab4defaa Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 15:43:59 +0200 Subject: [PATCH 218/314] new settings --- ego/scenario_setting.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 40b88ec6..f3aa4ab6 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -10,10 +10,14 @@ "eTraGo": { "method": "lopf", "pf_post_lopf": false, - "start_snapshot": 2952, - "end_snapshot" : 2953, + "start_snapshot": 1, + "end_snapshot" : 2, "solver": "gurobi", - "solver_options":{}, + "solver_options":{"threads":4, + "method":2, + "crossover":1, + "BarConvTol":"1.e-5", + "FeasibilityTol":"1.e-5"}, "scn_name": "NEP 2035", "scn_extension": null, "scn_decommissioning": null, @@ -21,7 +25,7 @@ "lpfile": false, "results": false, "export": false, - "extendable": "['network', 'storages']", + "extendable": "['network','storages']", "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, From ec7dada29da5b88e33867b2358def9bcd47c0972 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 16:01:28 +0200 Subject: [PATCH 219/314] add new options --- ego/scenario_setting.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 5b91a920..587baec0 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -25,11 +25,7 @@ "lpfile": false, "results": false, "export": false, -<<<<<<< HEAD "extendable": "['network','storages']", -======= - "extendable": [], ->>>>>>> 922690afb3df33d44831ea2880c18e9856e50133 "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, From c95e479253e9371f8de8a712bc5c5dc074e9ad7e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 16:09:02 +0200 Subject: [PATCH 220/314] add edisgo to api --- doc/api/ego.tools.rst | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/doc/api/ego.tools.rst b/doc/api/ego.tools.rst index 92ff212e..8f9dc6c9 100644 --- a/doc/api/ego.tools.rst +++ b/doc/api/ego.tools.rst @@ -12,6 +12,14 @@ ego\.tools\.economics module :undoc-members: :show-inheritance: +ego\.tools\.edisgo_integration module +------------------------------------- + +.. automodule:: ego.tools.edisgo_integration + :members: + :undoc-members: + :show-inheritance: + ego\.tools\.io module --------------------- @@ -20,6 +28,14 @@ ego\.tools\.io module :undoc-members: :show-inheritance: +ego\.tools\.mv_cluster module +----------------------------- + +.. automodule:: ego.tools.mv_cluster + :members: + :undoc-members: + :show-inheritance: + ego\.tools\.plots module ------------------------ @@ -34,8 +50,8 @@ ego\.tools\.results .. automodule:: ego.tools.results :members: :undoc-members: - :show-inheritance: - + :show-inheritance: + ego\.tools\.specs ----------------- @@ -44,7 +60,7 @@ ego\.tools\.specs :members: :undoc-members: :show-inheritance: - + ego\.tools\.storages -------------------- @@ -60,5 +76,3 @@ ego\.tools\.utilities module :members: :undoc-members: :show-inheritance: - - From e83f1306ae782e273b4e6d5f1466f86bcda4e546 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 16:09:35 +0200 Subject: [PATCH 221/314] update file --- doc/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api.rst b/doc/api.rst index 3ffe4d26..b5fffc92 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -1,7 +1,7 @@ .. make doc-string generated documentation appear here .. toctree:: - :maxdepth: 7 + :maxdepth: 3 :glob: From 758ad4423625d315c1fedbff6589979e9e609324 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 16:11:11 +0200 Subject: [PATCH 222/314] update file --- doc/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api.rst b/doc/api.rst index b5fffc92..1dce2d4a 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -1,7 +1,7 @@ .. make doc-string generated documentation appear here .. toctree:: - :maxdepth: 3 + :maxdepth: 4 :glob: From e42825f0bd0e1db9cc0cabd14242368bf4bf6f4f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 16:11:58 +0200 Subject: [PATCH 223/314] update file --- doc/api/ego.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/ego.rst b/doc/api/ego.rst index 436cb6a5..23ab3555 100644 --- a/doc/api/ego.rst +++ b/doc/api/ego.rst @@ -11,8 +11,8 @@ Subpackages Submodules ---------- -ego\.ego_main module --------------------- +ego\.ego_main +------------- .. automodule:: ego.ego_main :members: From 00b4a4e29c3345a90f23da1fa3a9ed1ac7c42ab8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 16:12:59 +0200 Subject: [PATCH 224/314] update file --- doc/api/ego.tools.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/api/ego.tools.rst b/doc/api/ego.tools.rst index 8f9dc6c9..d3295b39 100644 --- a/doc/api/ego.tools.rst +++ b/doc/api/ego.tools.rst @@ -4,40 +4,40 @@ ego\.tools package Submodules ---------- -ego\.tools\.economics module ----------------------------- +ego\.tools\.economics +--------------------- .. automodule:: ego.tools.economics :members: :undoc-members: :show-inheritance: -ego\.tools\.edisgo_integration module -------------------------------------- +ego\.tools\.edisgo_integration +------------------------------ .. automodule:: ego.tools.edisgo_integration :members: :undoc-members: :show-inheritance: -ego\.tools\.io module ---------------------- +ego\.tools\.io +-------------- .. automodule:: ego.tools.io :members: :undoc-members: :show-inheritance: -ego\.tools\.mv_cluster module ------------------------------ +ego\.tools\.mv_cluster +---------------------- .. automodule:: ego.tools.mv_cluster :members: :undoc-members: :show-inheritance: -ego\.tools\.plots module ------------------------- +ego\.tools\.plots +----------------- .. automodule:: ego.tools.plots :members: @@ -69,8 +69,8 @@ ego\.tools\.storages :undoc-members: :show-inheritance: -ego\.tools\.utilities module ----------------------------- +ego\.tools\.utilities +--------------------- .. automodule:: ego.tools.utilities :members: From a311db764fd863cbb177aeafe38fba848fe8e77b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 16:13:39 +0200 Subject: [PATCH 225/314] update file --- doc/api/modules.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index 1daaaa50..d1ab9079 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -3,5 +3,6 @@ ego .. toctree:: :maxdepth: 4 - + ego + ego.tools From b037c7615db642b7b8024bdbfe1e9ebbcdf8d1fc Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 17:07:06 +0200 Subject: [PATCH 226/314] remove empty df generator --- ego/tools/io.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 08824946..1f2bce4c 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -94,7 +94,6 @@ class egoBasic(object): def __init__(self, jsonpath, *args, **kwargs): - self.jsonpath = 'scenario_setting.json' self.json_file = get_scenario_setting(self.jsonpath) @@ -201,7 +200,6 @@ def __init__(self, jsonpath, *args, **kwargs): # add selected results to Results container self.etrago = pd.DataFrame() - self.etrago.generator = pd.DataFrame() self.etrago.storage_charges = total_storage_charges( self.etrago_network) self.etrago.storage_costs = etrago_storages(self.etrago_network) @@ -215,7 +213,6 @@ def __init__(self, jsonpath, *args, **kwargs): # add functions direct # self.etrago_network.etrago_line_loading = etrago_line_loading - pass if not 'READTHEDOCS' in os.environ: @@ -313,13 +310,12 @@ def __init__(self, jsonpath, *args, **kwargs): if self.json_file['global']['eDisGo'] is True: logger.info('Create eDisGo network') self.edisgo_networks = EDisGoNetworks( - json_file=self.json_file, - etrago_network=self.etrago_network) - + json_file=self.json_file, + etrago_network=self.etrago_network) + def edisgo_total_costs(self, **kwargs): - + return df - class eGo(eDisGoResults): From 5673d14a727c022a0b1286386b4632eb2873883c Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 17:16:25 +0200 Subject: [PATCH 227/314] update files --- doc/api/modules.rst | 2 +- ego/scenario_setting.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index d1ab9079..d533385e 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -4,5 +4,5 @@ ego .. toctree:: :maxdepth: 4 - ego + ego.ego_main ego.tools diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 587baec0..6a649527 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -4,7 +4,7 @@ "eDisGo": true, "db": "oedb", "result_id": 26, - "recover": true, + "recover": false, "gridversion": "v0.4.2" }, "eTraGo": { From e17be569445f586e46813e5d58b68114567be19f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Fri, 13 Jul 2018 17:23:39 +0200 Subject: [PATCH 228/314] update file --- doc/whatsnew/v0-2-0.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index d8db7b49..bed9b8a8 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -18,12 +18,12 @@ Added features -------------- * Cleaned and restructured eGo classes and functions - - Moved classes of eGo from results.py to io.py - - Move serveral function + * Moved classes of eGo from results.py to io.py + * Move serveral function * Introduce new files for edisgo handling - - edisgo_integration.py - - mv_cluster.py + * edisgo_integration.py + * mv_cluster.py * Introduce new file storages.py for eTraGo * Updated eTraGo 0.6 and integrated eTraGo's new functions and features to eGo From 31f042ada9048c888f1263793ce3c3310c4be296 Mon Sep 17 00:00:00 2001 From: maltesc Date: Mon, 16 Jul 2018 09:41:05 +0200 Subject: [PATCH 229/314] before economics change --- ego/tools/economics.py | 3 +- ego/tools/edisgo_integration.py | 158 ++++++++++++++++++-------------- 2 files changed, 88 insertions(+), 73 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index e4bad419..7edfeff9 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -79,7 +79,6 @@ def edisgo_convert_capital_costs(): json_file : :obj:dict Dictionary of the ``scenario_setting.json`` file - """ # eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 @@ -219,7 +218,7 @@ def etrago_grid_investment(network, json_file): pass -def edisgo_grid_investment(network): +def edisgo_grid_investment(edisgo_networks): """Function to get all costs of grid investment of eDisGo. Notes diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index a62edf3a..9bdf98bc 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -16,7 +16,7 @@ from egoio.db_tables import model_draft, grid from egoio.tools import db from edisgo.grid.network import Results, TimeSeriesControl -from edisgo.tools.pypsa_io import update_pypsa_timeseries +#from edisgo.tools.pypsa_io import update_pypsa_timeseries from edisgo.tools.edisgo_run import ( run_edisgo_basic, run_edisgo_pool_flexible @@ -80,19 +80,37 @@ def __init__(self, **kwargs): ## eTraGo self._etrago_network = kwargs.get('etrago_network', None) + self._edisgo_grids = {} + self._edisgo_costs = {} + ## Functions - self.grid_choice() - self.run_edisgo_pool() + self._set_grid_choice() + self._run_edisgo_pool() - - def analyze_cluster_attributes(self): + @property + def edisgo_grids(self): + """ + Returns all calculated MV grids as dictionary + + """ + return self._edisgo_grids + + @property + def edisgo_costs(self): + """ + Returns all calculated MV costs as dictionary + + """ + return self._edisgo_costs + + def _analyze_cluster_attributes(self): """ Analyses the attributes wind and solar capacity and farthest node for clustering. """ analyze_attributes(self._ding0_files) - def cluster_mv_grids(self, no_grids): + def _cluster_mv_grids(self, no_grids): """ Clusters the MV grids based on the attributes @@ -102,11 +120,15 @@ def cluster_mv_grids(self, no_grids): if not os.path.isfile(attributes_path): logger.info('Attributes file is missing') logger.info('Attributes will be calculated') - self.analyze_cluster_attributes() + self._analyze_cluster_attributes() return cluster_mv_grids(self._ding0_files, no_grids) - def check_available_mv_grids(self): + def _check_available_mv_grids(self): + """ + Checks all available MV grids in the given folder from the settings + + """ mv_grids = [] for file in os.listdir(self._ding0_files): @@ -118,12 +140,16 @@ def check_available_mv_grids(self): return mv_grids - def grid_choice(self): + def _set_grid_choice(self): + """ + Sets the grid choice based on the settings file + + """ if self._choice_mode == 'cluster': no_grids = self._edisgo_args['no_grids'] logger.info('Clustering to {} MV grids'.format(no_grids)) - cluster = self.cluster_mv_grids(no_grids) + cluster = self._cluster_mv_grids(no_grids) elif self._choice_mode == 'manual': man_grids = self._edisgo_args['manual_grids'] @@ -136,7 +162,7 @@ def grid_choice(self): ) elif self._choice_mode == 'all': - mv_grids = self.check_available_mv_grids() + mv_grids = self._check_available_mv_grids() cluster = pd.DataFrame( mv_grids, columns=['the_selected_network_id']) @@ -148,26 +174,26 @@ def grid_choice(self): self._grid_choice = cluster + def _run_edisgo_pool(self, parallelization=False): + """ + Runs eDisGo for the chosen grids - - - def run_edisgo_pool(self, parallelization=False): - + """ if parallelization is True: logger.info('Parallelization') - raise NotImplementedError + raise NotImplementedError +# # id_list = self._grid_choice['the_selected_network_id'].tolist() # # self._pool = run_edisgo_pool_flexible( # ding0_id_list=id_list, -# func=EDisGoNetworks.run_edisgo, -# func_arguments=['toll']) - - else: - - self._edisgo_grids = {} +# func=_run_edisgo, +# func_arguments=[ +# 'args...' +# ]) + else: no_grids = len(self._grid_choice) count = 0 for idx, row in self._grid_choice.iterrows(): @@ -181,16 +207,13 @@ def run_edisgo_pool(self, parallelization=False): 'MV grid {}'.format(mv_grid_id) ) try: - bus_id = self.get_bus_id_from_mv_grid(mv_grid_id) + edisgo_grid, costs = self._run_edisgo(mv_grid_id) self._edisgo_grids[ mv_grid_id - ] = self.run_edisgo( - mv_grid_id=mv_grid_id, - bus_id=bus_id, - session=self._session, - etrago_network=self._etrago_network, - scn_name=self._scn_name, - ding0_files=self._ding0_files) + ] = edisgo_grid + self._edisgo_costs[ + mv_grid_id + ] = costs except Exception: self._edisgo_grids[mv_grid_id] = None logger.exception( @@ -200,40 +223,34 @@ def run_edisgo_pool(self, parallelization=False): count += 1 - @staticmethod - def run_edisgo( - mv_grid_id, - bus_id, - session, - etrago_network, - scn_name, - ding0_files): + def _run_edisgo(self, mv_grid_id): """ Runs eDisGo with the desired settings. """ - + logger.info('Calculating interface values') + bus_id = self._get_bus_id_from_mv_grid(mv_grid_id) + specs = get_etragospecs_direct( - session, + self._session, bus_id, - etrago_network, - scn_name) + self._etrago_network, + self._scn_name) ding0_filepath = ( - ding0_files + self._ding0_files + '/ding0_grids__' + str(mv_grid_id) + '.pkl') - + if not os.path.isfile(ding0_filepath): msg = 'Not MV grid file for MV grid ID: ' + str(mv_grid_id) logger.error(msg) raise Exception(msg) - - + logger.info('Initial MV grid reinforcement (starting grid)') edisgo_grid, \ costs_before_geno_import, \ @@ -245,13 +262,13 @@ def run_edisgo( logger.info('eTraGo feed-in case') edisgo_grid.network.results = Results() - -# Generator Import is currently not working in eDisGo -# if self._generator_scn: -# edisgo_grid.import_generators( -# generator_scenario=self._generator_scn) + + # Generator Import is currently not working in eDisGo + # if self._generator_scn: + # edisgo_grid.import_generators( + # generator_scenario=self._generator_scn) - print(specs['conv_dispatch']) + edisgo_grid.network.timeseries = TimeSeriesControl( # Here, I use only normalized values from specs timeseries_generation_fluctuating=specs['potential'], @@ -259,25 +276,25 @@ def run_edisgo( timeseries_load='demandlib', config_data=edisgo_grid.network.config, timeindex=specs['conv_dispatch'].index).timeseries - -# This will be used after the next eDisGo release -# update_pypsa_timeseries( -# edisgo_grid.network, -# timesteps=specs['conv_dispatch'].index) + + # This will be used after the next eDisGo release + # update_pypsa_timeseries( + # edisgo_grid.network, + # timesteps=specs['conv_dispatch'].index) logger.warning('Curtailment can only be included after gen import') -# edisgo_grid.curtail(curtailment_methodology='curtail_all', -# # Here, I use absolute values -# timeseries_curtailment=specs['curtailment_abs']) -# -# # Think about the other curtailment functions!!!! + # edisgo_grid.curtail(curtailment_methodology='curtail_all', + # # Here, I use absolute values + # timeseries_curtailment=specs['curtailment_abs']) + # + # # Think about the other curtailment functions!!!! -# This will become unnecessary with the next eDisGo release + # This will become unnecessary with the next eDisGo release edisgo_grid.network.pypsa = None edisgo_grid.analyze() edisgo_grid.reinforce() - + # Get costs costs_grouped = \ edisgo_grid.network.results.grid_expansion_costs.groupby( @@ -289,12 +306,12 @@ def run_edisgo( costs.rename(columns={'level_0': 'grid'}, inplace=True) # Grid issues besser verstehen!! Und evtl. mit aussgeben - print(costs) - return edisgo_grid + return edisgo_grid, costs + ## Helpful tools - def get_mv_grid_from_bus_id(self, bus_id): + def _get_mv_grid_from_bus_id(self, bus_id): """ Returns the MV grid ID for a given eTraGo bus @@ -323,7 +340,7 @@ def get_mv_grid_from_bus_id(self, bus_id): return subst_id - def get_bus_id_from_mv_grid(self, subst_id): + def _get_bus_id_from_mv_grid(self, subst_id): """ Returns the eTraGo bus ID for a given MV grid @@ -351,7 +368,6 @@ def get_bus_id_from_mv_grid(self, subst_id): return bus_id - def get_hvmv_translation(self): + def _get_hvmv_translation(self): raise NotImplementedError - - + \ No newline at end of file From aaf436213691199fd2a932df4f2f3cb47563ee53 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 10:49:23 +0200 Subject: [PATCH 230/314] add eDisGo capital cost func - wip --- ego/tools/economics.py | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 1c332c66..3cf92a82 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -60,12 +60,13 @@ def annuity_per_period(capex, n, wacc, t, p): return capex * (wacc * (1 + wacc) ** n) / ((1 + wacc) ** n - 1) -def edisgo_convert_capital_costs(grid_components, json_file): - """ +def edisgo_convert_capital_costs(grid_components, cost_config, json_file): + """ Get scenario and calculation specific annuity cost by given capital + costs and lifetime. + Parameters ---------- - grid_components : :obj:dict Dictionary of ding0 grid components which are extendable (Name, investment_cost, lifetime) @@ -82,16 +83,34 @@ def edisgo_convert_capital_costs(grid_components, json_file): Returns ------- - capital_cost : - calculated capital costs of components + annuity_cost : numeric + Scenario and calculation specific annuity cost by given capital + costs and lifetime + + Examples + -------- + .. math:: + + PVA = (1 / _p) - (1 / (_p*(1 + _p) ** _T)) """ - # eTraGo calculation in + # Based on eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 - # def convert_capital_costs(network, start_snapshot, end_snapshot, - # p=0.05, T=40): - # Define function - pass + _T = 40 # from grid_components ? + _p = cost_config['p'] + + # Calculate present value of an annuity (PVA) + PVA = (1 / _p) - (1 / (_p*(1 + _p) ** _T)) + + year = 8760 + # get period of calculation + period = (json_file['eTraGo']['start_snapshot'] + - json_file['eTraGo']['start_snapshot']) + + # calculation of capital_cost + annuity_cost = (capital_cost / (PVA * (year/(period+1)))) + + return annuity_cost def etrago_operating_costs(network): From f0b5f549de0ec58a713e35d6bed85af0a607cc5e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 12:11:37 +0200 Subject: [PATCH 231/314] add v_level function --- ego/tools/economics.py | 46 +++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 3cf92a82..e78fe993 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -60,6 +60,12 @@ def annuity_per_period(capex, n, wacc, t, p): return capex * (wacc * (1 + wacc) ** n) / ((1 + wacc) ** n - 1) +# grid_components = {"hv_mv_transformer": "40 MVA", "mv_lv_transformer": "630 kVA", +# "mv_line": "NA2XS2Y 3x1x185 RM/25", "lv_line": "NAYY 4x1x150"} +# json_file = ego.json_file +# cost_config = {"p": 0.04} + + def edisgo_convert_capital_costs(grid_components, cost_config, json_file): """ Get scenario and calculation specific annuity cost by given capital costs and lifetime. @@ -195,14 +201,29 @@ def etrago_grid_investment(network, json_file): >>> ego = eGo(jsonpath='scenario_setting.json') >>> ego.etrago.grid_costs - +-----+---------------------+----------------+-----------+ - |v_nom| number_of_expansion | s_nom_expansion| grid_costs| - +=====+=====================+================+===========+ - | 380 | 27.0 | 12678.47943 |31514.1305 | - +-----+---------------------+----------------+-----------+ - | 220 | 0.0 | 0.0 | 0.0 | - +-----+---------------------+----------------+-----------+ + +-----+--------+-------------------+----------------+-----------+ + |v_nom| v_level|number_of_expansion| s_nom_expansion| grid_costs| + +=====+========+===================+================+===========+ + | 380 | ehv | 27.0 | 12678.47943 |31514.1305 | + +-----+--------+-------------------+----------------+-----------+ + | 110 | hv | 0.0 | 0.0 | 0.0 | + +-----+--------+-------------------+----------------+-----------+ """ + def v_level(lines): + """ Get v_level by v_nom + """ + + if lines['v_nom'] == 380.: + lines['v_level'] == 'ehv' + if lines['v_nom'] == 220.: + lines['v_level'] == 'ehv' + if lines['v_nom'] == 110.: + lines['v_level'] == 'hv' + else: + lines['v_level'] == 'unknown' + logger.info("Found unknown voltage leve: %s", lines['v_nom']) + + pass # check settings for extendable if 'network' not in json_file['eTraGo']['extendable']: @@ -220,19 +241,12 @@ def etrago_grid_investment(network, json_file): lines.capital_cost, axis='index') lines['number_of_expansion'] = lines.s_nom_expansion > 0.0 lines['time_step'] = get_time_steps(json_file) + lines['v_level'] = v_level(lines) - # print(get_time_steps(json_file)) - - #network.lines[['v_nom','capital_cost','s_nom', 's_nom_min','s_nom_opt']] - - # eTraGo Function: + # based on eTraGo Function: # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 # Definition https://pypsa.org/doc/components.html#line - # capital_cost - # s_nom_extendable - # check if extendable == true - return lines[['v_nom', 'number_of_expansion', 's_nom_expansion', 'grid_costs']].groupby('v_nom').sum() From f87493892f8581e5c5c54a6f9454b4872910c474 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 12:17:05 +0200 Subject: [PATCH 232/314] update forumal --- ego/tools/economics.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index e78fe993..b7ab68c6 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -97,7 +97,8 @@ def edisgo_convert_capital_costs(grid_components, cost_config, json_file): -------- .. math:: - PVA = (1 / _p) - (1 / (_p*(1 + _p) ** _T)) + PVA &= (1 / p_{interest rate}) \\ + &= (1 / (p_{interest rate}*(1 + p_{interest rate})^T_{Lifetime})) """ # Based on eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 From 4831449e2da8701f0297279eb7383e36ecf80d02 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 13:29:27 +0200 Subject: [PATCH 233/314] update file --- ego/tools/economics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index b7ab68c6..8e46673d 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -97,8 +97,8 @@ def edisgo_convert_capital_costs(grid_components, cost_config, json_file): -------- .. math:: - PVA &= (1 / p_{interest rate}) \\ - &= (1 / (p_{interest rate}*(1 + p_{interest rate})^T_{Lifetime})) + PVA = (1 / p_{interest rate}) - (1 / (p_{interest rate} + *(1 + p_{interest rate})^T_{Lifetime})) """ # Based on eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 From c43a0ad80f1c1cee8d850021856c39f199c2a559 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 13:30:42 +0200 Subject: [PATCH 234/314] update file --- ego/tools/economics.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 8e46673d..2835662d 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -98,16 +98,16 @@ def edisgo_convert_capital_costs(grid_components, cost_config, json_file): .. math:: PVA = (1 / p_{interest rate}) - (1 / (p_{interest rate} - *(1 + p_{interest rate})^T_{Lifetime})) + *(1 + p_{interest rate})^{T_{Lifetime}})) """ # Based on eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 - _T = 40 # from grid_components ? - _p = cost_config['p'] + T = 40 # from grid_components ? + p = cost_config['p'] # Calculate present value of an annuity (PVA) - PVA = (1 / _p) - (1 / (_p*(1 + _p) ** _T)) + PVA = (1 / p) - (1 / (p*(1 + p) ** T)) year = 8760 # get period of calculation From 675dddf772f6455c290997bfd16eba9e46d174c1 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 13:36:28 +0200 Subject: [PATCH 235/314] update file --- ego/tools/economics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 2835662d..32fdcd66 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -97,8 +97,8 @@ def edisgo_convert_capital_costs(grid_components, cost_config, json_file): -------- .. math:: - PVA = (1 / p_{interest rate}) - (1 / (p_{interest rate} - *(1 + p_{interest rate})^{T_{Lifetime}})) + PVA = \frac{\frac{1}{p_{rate}}}{(\frac{1}{p_{rate}}*(1 + \ + p_{rate})^{T_{Lifetime}})} """ # Based on eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 From 7a3ab5c437aa0304a98a361f78c114403d3a03fe Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 14:46:39 +0200 Subject: [PATCH 236/314] update file --- ego/tools/economics.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 32fdcd66..768cca92 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -202,13 +202,13 @@ def etrago_grid_investment(network, json_file): >>> ego = eGo(jsonpath='scenario_setting.json') >>> ego.etrago.grid_costs - +-----+--------+-------------------+----------------+-----------+ - |v_nom| v_level|number_of_expansion| s_nom_expansion| grid_costs| - +=====+========+===================+================+===========+ - | 380 | ehv | 27.0 | 12678.47943 |31514.1305 | - +-----+--------+-------------------+----------------+-----------+ - | 110 | hv | 0.0 | 0.0 | 0.0 | - +-----+--------+-------------------+----------------+-----------+ + +--------+-------------------+----------------+-----------+ + | v_level|number_of_expansion| s_nom_expansion| grid_costs| + +========+===================+================+===========+ + | ehv | 27.0 | 12678.47943 |31514.1305 | + +--------+-------------------+----------------+-----------+ + | hv | 0.0 | 0.0 | 0.0 | + s+--------+-------------------+----------------+-----------+ """ def v_level(lines): """ Get v_level by v_nom From e6b44786a2e13dee2abf865ac485709034ea09ce Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 14:47:07 +0200 Subject: [PATCH 237/314] remove func for testing --- ego/tools/io.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 1f2bce4c..78725698 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -207,8 +207,8 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago_network) self.etrago.generator = create_etrago_results(self.etrago_network, self.scn_name) - self.etrago.grid_costs = etrago_grid_investment(self.etrago_network, - self.json_file) + # self.etrago.grid_investment_costs = etrago_grid_investment(self.etrago_network, + # self.json_file) # add functions direct # self.etrago_network.etrago_line_loading = etrago_line_loading From a1abb5be8614cd1c58b72cd39321917ba15126df Mon Sep 17 00:00:00 2001 From: maltesc Date: Mon, 16 Jul 2018 14:47:19 +0200 Subject: [PATCH 238/314] edisgo costs aggregation finished --- ego/scenario_setting.json | 2 +- ego/tools/economics.py | 30 ++++++++++- ego/tools/edisgo_integration.py | 88 ++++++++++++++++++--------------- 3 files changed, 77 insertions(+), 43 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index c4ccb788..e3b6da69 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -41,7 +41,7 @@ "ding0_files": "data/MV_grids/20180713110719", "choice_mode": "manual", "no_grids": null, - "manual_grids": [1729, 1730], + "manual_grids": [1729, 1730, 1731, 1732, 1733], "scn_name": "NEP 2035", "comments": "make a comment" } diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 7edfeff9..9907bd2b 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -219,13 +219,41 @@ def etrago_grid_investment(network, json_file): def edisgo_grid_investment(edisgo_networks): + """Function to get all costs of grid investment of eDisGo. Notes ----- - ToDo add iteration and container of all costs of edisgo network """ - pass + + t = 40 + p=0.05 + logger.warning('For all components T={} and p={} is used'.format(t, p)) + + capital_costs = pd.DataFrame(columns=['v_lev', 'capital_costs']) + + for key, value in edisgo_networks.edisgo_grids.items(): + costs_grouped = value.network.results.grid_expansion_costs + costs_grouped.to_csv('test.csv') + costs_grouped = costs_grouped.rename( + columns={'voltage_level': 'v_lev'} + ) + + + costs_grouped['capital_costs'] = test(costs_grouped['total_costs']) + + costs_grouped = costs_grouped[['v_lev', 'capital_costs']] + + capital_costs = capital_costs.append(costs_grouped, ignore_index=True) + + aggr_capital_costs = capital_costs.groupby(['v_lev']).sum().reset_index() + aggr_capital_costs = aggr_capital_costs.rename( + columns={'capital_costs': 'grid_costs'} + ) + aggr_capital_costs['grid_costs'] = aggr_capital_costs['grid_costs'] * 1000 + + return aggr_capital_costs def get_generator_investment(network, scn_name): diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 9bdf98bc..29b24c04 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -81,7 +81,7 @@ def __init__(self, **kwargs): self._etrago_network = kwargs.get('etrago_network', None) self._edisgo_grids = {} - self._edisgo_costs = {} +# self._edisgo_costs = {} ## Functions self._set_grid_choice() @@ -95,13 +95,13 @@ def edisgo_grids(self): """ return self._edisgo_grids - @property - def edisgo_costs(self): - """ - Returns all calculated MV costs as dictionary - - """ - return self._edisgo_costs +# @property +# def edisgo_costs(self): +# """ +# Returns all calculated MV costs as dictionary +# +# """ +# return self._edisgo_costs def _analyze_cluster_attributes(self): """ @@ -207,13 +207,13 @@ def _run_edisgo_pool(self, parallelization=False): 'MV grid {}'.format(mv_grid_id) ) try: - edisgo_grid, costs = self._run_edisgo(mv_grid_id) + edisgo_grid = self._run_edisgo(mv_grid_id) self._edisgo_grids[ mv_grid_id ] = edisgo_grid - self._edisgo_costs[ - mv_grid_id - ] = costs +# self._edisgo_costs[ +# mv_grid_id +# ] = costs except Exception: self._edisgo_grids[mv_grid_id] = None logger.exception( @@ -230,15 +230,15 @@ def _run_edisgo(self, mv_grid_id): """ - logger.info('Calculating interface values') - - bus_id = self._get_bus_id_from_mv_grid(mv_grid_id) - - specs = get_etragospecs_direct( - self._session, - bus_id, - self._etrago_network, - self._scn_name) +# logger.info('Calculating interface values') +# +# bus_id = self._get_bus_id_from_mv_grid(mv_grid_id) +# +# specs = get_etragospecs_direct( +# self._session, +# bus_id, +# self._etrago_network, +# self._scn_name) ding0_filepath = ( self._ding0_files @@ -252,29 +252,35 @@ def _run_edisgo(self, mv_grid_id): raise Exception(msg) logger.info('Initial MV grid reinforcement (starting grid)') - edisgo_grid, \ - costs_before_geno_import, \ - grid_issues_before_geno_import = run_edisgo_basic( + edisgo_grid = run_edisgo_basic( ding0_filepath=ding0_filepath, generator_scenario=None, - analysis='worst-case') + analysis='worst-case')[0] # only the edisgo_grid is returned + + logger.warning('Function not fully executed!!') + return edisgo_grid logger.info('eTraGo feed-in case') edisgo_grid.network.results = Results() - # Generator Import is currently not working in eDisGo - # if self._generator_scn: - # edisgo_grid.import_generators( - # generator_scenario=self._generator_scn) +# Generator Import is currently not working in eDisGo + if self._generator_scn: + logger.info( + 'Importing generators for scenario {}'.format( + self._generator_scn) + ) + edisgo_grid.import_generators( + generator_scenario=self._generator_scn) edisgo_grid.network.timeseries = TimeSeriesControl( + network=edisgo_grid.network, # Here, I use only normalized values from specs timeseries_generation_fluctuating=specs['potential'], timeseries_generation_dispatchable=specs['conv_dispatch'], timeseries_load='demandlib', - config_data=edisgo_grid.network.config, +# config_data=edisgo_grid.network.config, timeindex=specs['conv_dispatch'].index).timeseries # This will be used after the next eDisGo release @@ -290,23 +296,23 @@ def _run_edisgo(self, mv_grid_id): # # Think about the other curtailment functions!!!! # This will become unnecessary with the next eDisGo release - edisgo_grid.network.pypsa = None +# edisgo_grid.analyze() edisgo_grid.reinforce() - # Get costs - costs_grouped = \ - edisgo_grid.network.results.grid_expansion_costs.groupby( - ['type']).sum() - costs = pd.DataFrame(costs_grouped.values, - columns=costs_grouped.columns, - index=[[edisgo_grid.network.id] * len(costs_grouped), - costs_grouped.index]).reset_index() - costs.rename(columns={'level_0': 'grid'}, inplace=True) +# # Get costs +# costs_grouped = \ +# edisgo_grid.network.results.grid_expansion_costs.groupby( +# ['type']).sum() +# costs = pd.DataFrame(costs_grouped.values, +# columns=costs_grouped.columns, +# index=[[edisgo_grid.network.id] * len(costs_grouped), +# costs_grouped.index]).reset_index() +# costs.rename(columns={'level_0': 'grid'}, inplace=True) # Grid issues besser verstehen!! Und evtl. mit aussgeben - return edisgo_grid, costs + return edisgo_grid From 552216f585bdb11810a20780ecaeef4442d0cabe Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 16:03:12 +0200 Subject: [PATCH 239/314] fix line costs --- ego/tools/economics.py | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 768cca92..b0ee1321 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -202,29 +202,14 @@ def etrago_grid_investment(network, json_file): >>> ego = eGo(jsonpath='scenario_setting.json') >>> ego.etrago.grid_costs - +--------+-------------------+----------------+-----------+ - | v_level|number_of_expansion| s_nom_expansion| grid_costs| - +========+===================+================+===========+ - | ehv | 27.0 | 12678.47943 |31514.1305 | - +--------+-------------------+----------------+-----------+ - | hv | 0.0 | 0.0 | 0.0 | - s+--------+-------------------+----------------+-----------+ + +--------+-------------------+------------+ + | v_level|number_of_expansion| grid_costs| + +========+===================+============+ + | ehv | 27.0 | 31514.1305 | + +--------+-------------------+------------+ + | hv | 0.0 | 0.0 | + +--------+-------------------+------------+ """ - def v_level(lines): - """ Get v_level by v_nom - """ - - if lines['v_nom'] == 380.: - lines['v_level'] == 'ehv' - if lines['v_nom'] == 220.: - lines['v_level'] == 'ehv' - if lines['v_nom'] == 110.: - lines['v_level'] == 'hv' - else: - lines['v_level'] == 'unknown' - logger.info("Found unknown voltage leve: %s", lines['v_nom']) - - pass # check settings for extendable if 'network' not in json_file['eTraGo']['extendable']: @@ -242,7 +227,15 @@ def v_level(lines): lines.capital_cost, axis='index') lines['number_of_expansion'] = lines.s_nom_expansion > 0.0 lines['time_step'] = get_time_steps(json_file) - lines['v_level'] = v_level(lines) + + # add v_level + lines['v_level'] = 'unknown' + + ix_ehv = lines[lines['v_nom'] >= 380].index + lines.set_value(ix_ehv, 'v_level', 'ehv') + + ix_hv = lines[(lines['v_nom'] <= 220) & (lines['v_nom'] >= 110)].index + lines.set_value(ix_hv, 'v_level', 'hv') # based on eTraGo Function: # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 From 5ca58031dc0e9b10547b6ae9d16936d8516fd8bd Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 16:03:22 +0200 Subject: [PATCH 240/314] update file --- ego/tools/io.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 78725698..3a14bb42 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -207,8 +207,8 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago_network) self.etrago.generator = create_etrago_results(self.etrago_network, self.scn_name) - # self.etrago.grid_investment_costs = etrago_grid_investment(self.etrago_network, - # self.json_file) + self.etrago.grid_investment_costs = etrago_grid_investment(self.etrago_network, + self.json_file) # add functions direct # self.etrago_network.etrago_line_loading = etrago_line_loading From 2941e538ef1cc0a328d53d6d78a870163565bd93 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 16:11:00 +0200 Subject: [PATCH 241/314] update grid costs --- ego/tools/economics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index b0ee1321..307d07d5 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -241,7 +241,7 @@ def etrago_grid_investment(network, json_file): # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 # Definition https://pypsa.org/doc/components.html#line - return lines[['v_nom', 'number_of_expansion', 's_nom_expansion', + return lines[['v_level', 'number_of_expansion', 'grid_costs']].groupby('v_nom').sum() # ToDo: add .agg({'number_of_expansion':lambda x: x.count(), From 8a56ef77a9bc6d38a54bf530934c85e98e31e493 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 16:43:59 +0200 Subject: [PATCH 242/314] add trafo costs to etrago_grid_investment --- ego/tools/economics.py | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 307d07d5..128d9877 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -241,8 +241,39 @@ def etrago_grid_investment(network, json_file): # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 # Definition https://pypsa.org/doc/components.html#line - return lines[['v_level', 'number_of_expansion', - 'grid_costs']].groupby('v_nom').sum() + # get costs of transfomers + trafos = network.transformers[['v_nom0', 'v_nom1', 'capital_cost', + 's_nom_extendable', 's_nom', 's_nom_opt']] + + trafos['s_nom_extendable'] = trafos.s_nom_opt.subtract( + trafos.s_nom, axis='index') + trafos['grid_costs'] = trafos.s_nom_extendable.multiply( + trafos.capital_cost, axis='index') + trafos['number_of_expansion'] = trafos.s_nom_extendable > 0.0 + + # add v_level + trafos['v_level'] = 'unknown' + + # TODO check + ix_ehv = trafos[trafos['v_nom0'] >= 380].index + trafos.set_value(ix_ehv, 'v_level', 'ehv') + + ix_hv = trafos[(trafos['v_nom0'] <= 220) & + (trafos['v_nom0'] >= 110)].index + trafos.set_value(ix_hv, 'v_level', 'hv') + + # aggregate lines and trafo + line = lines[['v_level', 'number_of_expansion', + 'grid_costs', 'time_step']].groupby('v_level').sum() + trafo = trafos[['v_level', 'number_of_expansion', + 'grid_costs', 'time_step']].groupby('v_level').sum() + + # merge trafos and line + frames = [line, trafo] + + result = pd.concat(frames) + + return result # ToDo: add .agg({'number_of_expansion':lambda x: x.count(), # 's_nom_expansion': np.sum, From a5b099ff3b67c0290f83a40547e32ec73ce220a8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 16:52:49 +0200 Subject: [PATCH 243/314] update file --- ego/tools/economics.py | 63 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 128d9877..a76f8b1d 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -144,7 +144,7 @@ def etrago_operating_costs(network): # TODO - seperate operation costs in other functions ? etg = network - #etg = eTraGo + # etg = eTraGo # groupby v_nom power_price = etg.generators_t.p[etg.generators[etg.generators. control != 'Slack'].index] * etg.generators.\ @@ -250,28 +250,29 @@ def etrago_grid_investment(network, json_file): trafos['grid_costs'] = trafos.s_nom_extendable.multiply( trafos.capital_cost, axis='index') trafos['number_of_expansion'] = trafos.s_nom_extendable > 0.0 + trafos['time_step'] = get_time_steps(json_fi # add v_level - trafos['v_level'] = 'unknown' + trafos['v_level']='unknown' # TODO check - ix_ehv = trafos[trafos['v_nom0'] >= 380].index + ix_ehv=trafos[trafos['v_nom0'] >= 380].index trafos.set_value(ix_ehv, 'v_level', 'ehv') - ix_hv = trafos[(trafos['v_nom0'] <= 220) & + ix_hv=trafos[(trafos['v_nom0'] <= 220) & (trafos['v_nom0'] >= 110)].index trafos.set_value(ix_hv, 'v_level', 'hv') # aggregate lines and trafo - line = lines[['v_level', 'number_of_expansion', + line=lines[['v_level', 'number_of_expansion', 'grid_costs', 'time_step']].groupby('v_level').sum() - trafo = trafos[['v_level', 'number_of_expansion', + trafo=trafos[['v_level', 'number_of_expansion', 'grid_costs', 'time_step']].groupby('v_level').sum() # merge trafos and line - frames = [line, trafo] + frames=[line, trafo] - result = pd.concat(frames) + result=pd.concat(frames) return result @@ -304,28 +305,28 @@ def get_generator_investment(network, scn_name): # TODO - change values in csv # - add values to database - etg = network + etg=network - path = os.getcwd() - filename = 'investment_costs.csv' - invest = pd.DataFrame.from_csv(path + '/data/'+filename) + path=os.getcwd() + filename='investment_costs.csv' + invest=pd.DataFrame.from_csv(path + '/data/'+filename) if scn_name in ['SH Status Quo', 'Status Quo']: - invest_scn = 'Status Quo' + invest_scn='Status Quo' if scn_name in ['SH NEP 2035', 'NEP 2035']: - invest_scn = 'NEP 2035' + invest_scn='NEP 2035' if scn_name in ['SH eGo 100', 'eGo 100']: - invest_scn = 'eGo 100' + invest_scn='eGo 100' - gen_invest = pd.concat([invest[invest_scn], + gen_invest=pd.concat([invest[invest_scn], etg.generators.groupby('carrier')['p_nom'].sum()], axis=1, join='inner') - gen_invest = pd.concat([invest[invest_scn], etg.generators.groupby('carrier') + gen_invest=pd.concat([invest[invest_scn], etg.generators.groupby('carrier') ['p_nom'].sum()], axis=1, join='inner') - gen_invest['carrier_costs'] = gen_invest[invest_scn] * \ + gen_invest['carrier_costs']=gen_invest[invest_scn] * \ gen_invest['p_nom'] * 1000 # in MW return gen_invest @@ -345,40 +346,40 @@ def investment_costs(network): """ # TODO add edisgo - etg = network - invest = pd.DataFrame() + etg=network + invest=pd.DataFrame() # storages # get total storage investment costs # unit of costs? - installed_storages = etg.storage_units[etg.storage_units.p_nom_opt != 0] - costs = sum(installed_storages.capital_cost * installed_storages.p_nom_opt) - invest = invest.append({'storage_costs': costs}, ignore_index=True) + installed_storages=etg.storage_units[etg.storage_units.p_nom_opt != 0] + costs=sum(installed_storages.capital_cost * installed_storages.p_nom_opt) + invest=invest.append({'storage_costs': costs}, ignore_index=True) # get storage costs per voltage level - loc = etg.storage_units[etg.storage_units.p_nom_opt != 0]['bus'] - v_level = etg.buses.loc[loc, :]['v_nom'] - installed_storages = installed_storages.assign(v_nom=0) + loc=etg.storage_units[etg.storage_units.p_nom_opt != 0]['bus'] + v_level=etg.buses.loc[loc, :]['v_nom'] + installed_storages=installed_storages.assign(v_nom=0) for i, k in v_level.iteritems(): installed_storages.loc[installed_storages[installed_storages.bus == - i].index, 'v_nom'] = k + i].index, 'v_nom']=k - storage_level = installed_storages.groupby('v_nom')['capital_cost'].sum() + storage_level=installed_storages.groupby('v_nom')['capital_cost'].sum() # Line extentation costs # (eTraGo.lines.s_nom_opt - eTraGo.lines.s_nom) * eTraGo.lines.capital_cost - line_expen = (etg.lines.groupby('v_nom')['s_nom_opt'].sum() + line_expen=(etg.lines.groupby('v_nom')['s_nom_opt'].sum() - etg.lines.groupby('v_nom')['s_nom'].sum()) if line_expen.sum() <= 0: print('Warning: !line extentation, set random costs for plotting!') - lines_level = pd.DataFrame([[110., 722*np.exp(8)], [220., 822*np.exp(8)], + lines_level=pd.DataFrame([[110., 722*np.exp(8)], [220., 822*np.exp(8)], [380., 999*np.exp(9)]], columns=['v_nom', 'capital_cost']).\ groupby('v_nom')['capital_cost'].sum() - invest = invest.assign(line_costs=lines_level.sum()) + invest=invest.assign(line_costs=lines_level.sum()) # invest.transpose() From a5050eb6626f49c95333424bc7c638ad50b7e31f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 16:54:09 +0200 Subject: [PATCH 244/314] update file --- ego/tools/economics.py | 62 +++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index a76f8b1d..40a2ef0b 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -250,29 +250,29 @@ def etrago_grid_investment(network, json_file): trafos['grid_costs'] = trafos.s_nom_extendable.multiply( trafos.capital_cost, axis='index') trafos['number_of_expansion'] = trafos.s_nom_extendable > 0.0 - trafos['time_step'] = get_time_steps(json_fi + trafos['time_step'] = get_time_steps(json_file) # add v_level - trafos['v_level']='unknown' + trafos['v_level'] = 'unknown' # TODO check - ix_ehv=trafos[trafos['v_nom0'] >= 380].index + ix_ehv = trafos[trafos['v_nom0'] >= 380].index trafos.set_value(ix_ehv, 'v_level', 'ehv') - ix_hv=trafos[(trafos['v_nom0'] <= 220) & + ix_hv = trafos[(trafos['v_nom0'] <= 220) & (trafos['v_nom0'] >= 110)].index trafos.set_value(ix_hv, 'v_level', 'hv') # aggregate lines and trafo - line=lines[['v_level', 'number_of_expansion', + line = lines[['v_level', 'number_of_expansion', 'grid_costs', 'time_step']].groupby('v_level').sum() - trafo=trafos[['v_level', 'number_of_expansion', + trafo = trafos[['v_level', 'number_of_expansion', 'grid_costs', 'time_step']].groupby('v_level').sum() # merge trafos and line - frames=[line, trafo] + frames = [line, trafo] - result=pd.concat(frames) + result = pd.concat(frames) return result @@ -305,28 +305,28 @@ def get_generator_investment(network, scn_name): # TODO - change values in csv # - add values to database - etg=network + etg = network - path=os.getcwd() - filename='investment_costs.csv' - invest=pd.DataFrame.from_csv(path + '/data/'+filename) + path = os.getcwd() + filename = 'investment_costs.csv' + invest = pd.DataFrame.from_csv(path + '/data/'+filename) if scn_name in ['SH Status Quo', 'Status Quo']: - invest_scn='Status Quo' + invest_scn = 'Status Quo' if scn_name in ['SH NEP 2035', 'NEP 2035']: - invest_scn='NEP 2035' + invest_scn = 'NEP 2035' if scn_name in ['SH eGo 100', 'eGo 100']: - invest_scn='eGo 100' + invest_scn = 'eGo 100' - gen_invest=pd.concat([invest[invest_scn], + gen_invest = pd.concat([invest[invest_scn], etg.generators.groupby('carrier')['p_nom'].sum()], axis=1, join='inner') - gen_invest=pd.concat([invest[invest_scn], etg.generators.groupby('carrier') + gen_invest = pd.concat([invest[invest_scn], etg.generators.groupby('carrier') ['p_nom'].sum()], axis=1, join='inner') - gen_invest['carrier_costs']=gen_invest[invest_scn] * \ + gen_invest['carrier_costs'] = gen_invest[invest_scn] * \ gen_invest['p_nom'] * 1000 # in MW return gen_invest @@ -346,40 +346,40 @@ def investment_costs(network): """ # TODO add edisgo - etg=network - invest=pd.DataFrame() + etg = network + invest = pd.DataFrame() # storages # get total storage investment costs # unit of costs? - installed_storages=etg.storage_units[etg.storage_units.p_nom_opt != 0] - costs=sum(installed_storages.capital_cost * installed_storages.p_nom_opt) - invest=invest.append({'storage_costs': costs}, ignore_index=True) + installed_storages = etg.storage_units[etg.storage_units.p_nom_opt != 0] + costs = sum(installed_storages.capital_cost * installed_storages.p_nom_opt) + invest = invest.append({'storage_costs': costs}, ignore_index=True) # get storage costs per voltage level - loc=etg.storage_units[etg.storage_units.p_nom_opt != 0]['bus'] - v_level=etg.buses.loc[loc, :]['v_nom'] - installed_storages=installed_storages.assign(v_nom=0) + loc = etg.storage_units[etg.storage_units.p_nom_opt != 0]['bus'] + v_level = etg.buses.loc[loc, :]['v_nom'] + installed_storages = installed_storages.assign(v_nom=0) for i, k in v_level.iteritems(): installed_storages.loc[installed_storages[installed_storages.bus == - i].index, 'v_nom']=k + i].index, 'v_nom'] = k - storage_level=installed_storages.groupby('v_nom')['capital_cost'].sum() + storage_level = installed_storages.groupby('v_nom')['capital_cost'].sum() # Line extentation costs # (eTraGo.lines.s_nom_opt - eTraGo.lines.s_nom) * eTraGo.lines.capital_cost - line_expen=(etg.lines.groupby('v_nom')['s_nom_opt'].sum() + line_expen = (etg.lines.groupby('v_nom')['s_nom_opt'].sum() - etg.lines.groupby('v_nom')['s_nom'].sum()) if line_expen.sum() <= 0: print('Warning: !line extentation, set random costs for plotting!') - lines_level=pd.DataFrame([[110., 722*np.exp(8)], [220., 822*np.exp(8)], + lines_level = pd.DataFrame([[110., 722*np.exp(8)], [220., 822*np.exp(8)], [380., 999*np.exp(9)]], columns=['v_nom', 'capital_cost']).\ groupby('v_nom')['capital_cost'].sum() - invest=invest.assign(line_costs=lines_level.sum()) + invest = invest.assign(line_costs=lines_level.sum()) # invest.transpose() From 0c83e2447cbe32ac38667b70fb661e7470cfe6d1 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 16 Jul 2018 16:58:36 +0200 Subject: [PATCH 245/314] update file --- ego/tools/economics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 40a2ef0b..e17fb9ad 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -265,9 +265,9 @@ def etrago_grid_investment(network, json_file): # aggregate lines and trafo line = lines[['v_level', 'number_of_expansion', - 'grid_costs', 'time_step']].groupby('v_level').sum() + 'grid_costs']].groupby('v_level').sum() trafo = trafos[['v_level', 'number_of_expansion', - 'grid_costs', 'time_step']].groupby('v_level').sum() + 'grid_costs']].groupby('v_level').sum() # merge trafos and line frames = [line, trafo] From 561614b513aae7406580689a8122cff0844490a0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 09:15:24 +0200 Subject: [PATCH 246/314] update of docu --- README.rst | 61 ++++++++++++++++++++++++---------- doc/index.rst | 4 +++ doc/theoretical_background.rst | 7 ++-- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/README.rst b/README.rst index 7f332654..f49e6742 100644 --- a/README.rst +++ b/README.rst @@ -1,18 +1,23 @@ -.. image:: https://readthedocs.org/projects/openego/badge/?version=latest - :target: http://openego.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status +|readthedocs| |badge_githubstars| + .. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 + :align: right + :scale: 100% + +*A cross-grid-level electricity grid and storage optimization tool* +| `openegoproject.wordpress.com `_ + eGo -==== +=== Integrated optimization of flexibility options and grid extension measures -for power grids based on eTraGo and eDisGo. +for power grids based on `eTraGo `_ and +`eDisGo `_. -A speciality in this context is that transmission grids are described by -the 380, 220 and 110 kV in Germany. The integration of the transmission grid -(via eTraGo) and distribution grid (via eDisGo) is part of eGo. +The Documentation of the eGo tool can be found on +`openego.readthedocs.io Fork me on GitHub diff --git a/doc/theoretical_background.rst b/doc/theoretical_background.rst index 41003551..982262da 100644 --- a/doc/theoretical_background.rst +++ b/doc/theoretical_background.rst @@ -2,8 +2,7 @@ Theoretical background ====================== - - +.. contents:: Models overview @@ -17,8 +16,12 @@ Models overview :alt: Overview of Models and processes which are used by eGo :align: center +Cluster methods +=============== +Economic calculation +==================== References From 0c281909963b6273ec275ab1b75a312cb8a4120e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 10:24:23 +0200 Subject: [PATCH 247/314] update docu --- doc/api/modules.rst | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index d533385e..e4f2321c 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -1,6 +1,37 @@ +=== ego === +ego_main.py +=========== + + +Run the ``ego_main.py`` file with: + +.. code-block:: bash + + >>> python3 ego_main.py + >>> ... + >>> INFO:ego:Start calculation + >>> ... + + + +.. code-block:: python + + >>> from ego.tools.io import eGo + >>> ego = eGo(jsonpath='scenario_setting.json') + >>> ego.etrago_line_loading() + >>> print(ego.etrago.storage_costs) + >>> ... + >>> INFO:ego:Start calculation + >>> ... + + +Overview of modules +=================== + + .. toctree:: :maxdepth: 4 From 881ef579bfaab8557b780a81431576a3847286b9 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 10:25:49 +0200 Subject: [PATCH 248/314] update docu --- ego/tools/io.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ego/tools/io.py b/ego/tools/io.py index 3a14bb42..04c35231 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -309,6 +309,7 @@ def __init__(self, jsonpath, *args, **kwargs): if self.json_file['global']['eDisGo'] is True: logger.info('Create eDisGo network') + self.edisgo_networks = EDisGoNetworks( json_file=self.json_file, etrago_network=self.etrago_network) From 3e2e6907c32bd06f36ab7ed2e1f25cb08d4eb795 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 10:28:18 +0200 Subject: [PATCH 249/314] update docu --- README.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index f49e6742..9ea0166d 100644 --- a/README.rst +++ b/README.rst @@ -14,9 +14,8 @@ eGo Integrated optimization of flexibility options and grid extension measures for power grids based on `eTraGo `_ and -`eDisGo `_. - -The Documentation of the eGo tool can be found on +`eDisGo `_. The Documentation of the eGo tool +can be found on `openego.readthedocs.io Date: Tue, 17 Jul 2018 10:57:37 +0200 Subject: [PATCH 250/314] update docu --- doc/api/modules.rst | 26 +-- doc/getting_started.rst | 2 +- doc/index.rst | 2 + doc/whatsnew/v0-2-0.rst | 4 +- ego/ego_main.py | 5 +- ego/tools/edisgo_integration.py | 321 ++++++++++++++++---------------- 6 files changed, 179 insertions(+), 181 deletions(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index e4f2321c..42b02230 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -2,6 +2,19 @@ ego === + + +Overview of modules +=================== + + +.. toctree:: + :maxdepth: 4 + + ego.ego_main + ego.tools + + ego_main.py =========== @@ -15,7 +28,7 @@ Run the ``ego_main.py`` file with: >>> INFO:ego:Start calculation >>> ... - +The eGo App works like: .. code-block:: python @@ -26,14 +39,3 @@ Run the ``ego_main.py`` file with: >>> ... >>> INFO:ego:Start calculation >>> ... - - -Overview of modules -=================== - - -.. toctree:: - :maxdepth: 4 - - ego.ego_main - ego.tools diff --git a/doc/getting_started.rst b/doc/getting_started.rst index 84560d64..45eb747a 100644 --- a/doc/getting_started.rst +++ b/doc/getting_started.rst @@ -37,6 +37,6 @@ Examples Example Cluster of Germany ========================== - .. raw:: html :file: images/iplot_cluster.html + diff --git a/doc/index.rst b/doc/index.rst index 182314f6..e3511a47 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -41,5 +41,7 @@ Indices and tables * :ref:`search` + .. raw:: html Fork me on GitHub + diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index bed9b8a8..b0bfdfd3 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -1,4 +1,4 @@ -Release v0.2.0 (July 17, 2018) +Release v0.2.0 (July 18, 2018) ++++++++++++++++++++++++++++++ Second release of the eGo application. @@ -20,7 +20,7 @@ Added features * Cleaned and restructured eGo classes and functions * Moved classes of eGo from results.py to io.py * Move serveral function - + * Introduce new files for edisgo handling * edisgo_integration.py * mv_cluster.py diff --git a/ego/ego_main.py b/ego/ego_main.py index 5334dae2..b03f3dcc 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -29,11 +29,12 @@ import pandas as pd import os -from ego.tools.utilities import define_logging -logger = define_logging(log_name='ego.log') + if not 'READTHEDOCS' in os.environ: from ego.tools.io import eGo + from ego.tools.utilities import define_logging + logger = define_logging(log_name='ego.log') __copyright__ = ("Flensburg University of Applied Sciences, " "Europa-Universität Flensburg, " diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index a62edf3a..f3a2edff 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -1,6 +1,6 @@ """ -This file is part of the the eGo toolbox. -It contains the class definition for multiple eDisGo networks and results. +This file is part of the the eGo toolbox. +It contains the class definition for multiple eDisGo networks and results. """ __copyright__ = ("Flensburg University of Applied Sciences, " @@ -10,28 +10,29 @@ __author__ = "wolf_bunke,maltesc" # Import -## Local Packages - -## Project Packages -from egoio.db_tables import model_draft, grid -from egoio.tools import db -from edisgo.grid.network import Results, TimeSeriesControl -from edisgo.tools.pypsa_io import update_pypsa_timeseries -from edisgo.tools.edisgo_run import ( +# Local Packages + +# Project Packages +if not 'READTHEDOCS' in os.environ: + from egoio.db_tables import model_draft, grid + from egoio.tools import db + from edisgo.grid.network import Results, TimeSeriesControl + #from edisgo.tools.pypsa_io import update_pypsa_timeseries + from edisgo.tools.edisgo_run import ( run_edisgo_basic, run_edisgo_pool_flexible - ) -from ego.tools.specs import ( + ) + from ego.tools.specs import ( get_etragospecs_direct, -# get_feedin_fluctuating, -# get_curtailment - ) -from ego.tools.mv_cluster import ( + # get_feedin_fluctuating, + # get_curtailment + ) + from ego.tools.mv_cluster import ( analyze_attributes, cluster_mv_grids) -from ego.tools.utilities import define_logging + from ego.tools.utilities import define_logging -## Other Packages +# Other Packages import os import logging import multiprocessing as mp @@ -39,10 +40,10 @@ from sqlalchemy.orm import sessionmaker # Logging -logging.basicConfig(format='%(asctime)s %(message)s',level=logging.INFO) +logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) logger = logging.getLogger('ego') - + class EDisGoNetworks: """ Represents multiple eDisGo networks. @@ -50,76 +51,75 @@ class EDisGoNetworks: """ def __init__(self, **kwargs): - + conn = db.connection(section='oedb') Session = sessionmaker(bind=conn) self._session = Session() - ## Json Inputs + # Json Inputs self._json_file = kwargs.get('json_file', None) self._grid_version = self._json_file['global']['gridversion'] - - ### eDisGo args - self._edisgo_args = self._json_file['eDisGo'] + + # eDisGo args + self._edisgo_args = self._json_file['eDisGo'] self._ding0_files = self._edisgo_args['ding0_files'] self._choice_mode = self._edisgo_args['choice_mode'] - - self._scn_name = self._edisgo_args['scn_name'] + + self._scn_name = self._edisgo_args['scn_name'] if self._scn_name == 'Status Quo': self._generator_scn = None elif self._scn_name == 'NEP 2035': self._generator_scn = 'nep2035' elif self._scn_name == 'eGo100': self._generator_scn = 'ego100' - + if self._grid_version is not None: - self._versioned = True + self._versioned = True else: self._versioned = False - - ## eTraGo + + # eTraGo self._etrago_network = kwargs.get('etrago_network', None) - - ## Functions + + # Functions self.grid_choice() self.run_edisgo_pool() - def analyze_cluster_attributes(self): """ Analyses the attributes wind and solar capacity and farthest node for clustering. """ analyze_attributes(self._ding0_files) - + def cluster_mv_grids(self, no_grids): """ Clusters the MV grids based on the attributes - """ + """ attributes_path = self._ding0_files + '/attributes.csv' - + if not os.path.isfile(attributes_path): logger.info('Attributes file is missing') logger.info('Attributes will be calculated') self.analyze_cluster_attributes() return cluster_mv_grids(self._ding0_files, no_grids) - + def check_available_mv_grids(self): - + mv_grids = [] for file in os.listdir(self._ding0_files): if file.endswith('.pkl'): mv_grids.append( - int(file.replace( - 'ding0_grids__', '' - ).replace('.pkl', ''))) - + int(file.replace( + 'ding0_grids__', '' + ).replace('.pkl', ''))) + return mv_grids - + def grid_choice(self): - + if self._choice_mode == 'cluster': no_grids = self._edisgo_args['no_grids'] logger.info('Clustering to {} MV grids'.format(no_grids)) @@ -128,155 +128,150 @@ def grid_choice(self): elif self._choice_mode == 'manual': man_grids = self._edisgo_args['manual_grids'] cluster = pd.DataFrame( - man_grids, - columns=['the_selected_network_id']) + man_grids, + columns=['the_selected_network_id']) cluster['no_of_points_per_cluster'] = 1 logger.info( - 'Calculating manually chosen MV grids {}'.format(man_grids) - ) - + 'Calculating manually chosen MV grids {}'.format(man_grids) + ) + elif self._choice_mode == 'all': mv_grids = self.check_available_mv_grids() cluster = pd.DataFrame( - mv_grids, - columns=['the_selected_network_id']) + mv_grids, + columns=['the_selected_network_id']) cluster['no_of_points_per_cluster'] = 1 no_grids = len(mv_grids) logger.info( - 'Calculating all available {} MV grids'.format(no_grids) - ) + 'Calculating all available {} MV grids'.format(no_grids) + ) self._grid_choice = cluster - - - - + def run_edisgo_pool(self, parallelization=False): - + if parallelization is True: logger.info('Parallelization') raise NotImplementedError - + # id_list = self._grid_choice['the_selected_network_id'].tolist() -# +# # self._pool = run_edisgo_pool_flexible( -# ding0_id_list=id_list, +# ding0_id_list=id_list, # func=EDisGoNetworks.run_edisgo, -# func_arguments=['toll']) - +# func_arguments=['toll']) + else: - + self._edisgo_grids = {} - + no_grids = len(self._grid_choice) count = 0 for idx, row in self._grid_choice.iterrows(): prog = '%.1f' % (count / no_grids * 100) logger.info( - '{} % Calculated by eDisGo'.format(prog) - ) - + '{} % Calculated by eDisGo'.format(prog) + ) + mv_grid_id = int(row['the_selected_network_id']) logger.info( - 'MV grid {}'.format(mv_grid_id) - ) + 'MV grid {}'.format(mv_grid_id) + ) try: bus_id = self.get_bus_id_from_mv_grid(mv_grid_id) self._edisgo_grids[ - mv_grid_id - ] = self.run_edisgo( - mv_grid_id=mv_grid_id, - bus_id=bus_id, - session=self._session, - etrago_network=self._etrago_network, - scn_name=self._scn_name, - ding0_files=self._ding0_files) + mv_grid_id + ] = self.run_edisgo( + mv_grid_id=mv_grid_id, + bus_id=bus_id, + session=self._session, + etrago_network=self._etrago_network, + scn_name=self._scn_name, + ding0_files=self._ding0_files) except Exception: self._edisgo_grids[mv_grid_id] = None logger.exception( - 'MV grid {} failed: \n'.format(mv_grid_id) - - ) - + 'MV grid {} failed: \n'.format(mv_grid_id) + + ) + count += 1 - - @staticmethod + + @staticmethod def run_edisgo( - mv_grid_id, + mv_grid_id, bus_id, session, etrago_network, scn_name, ding0_files): - """ - Runs eDisGo with the desired settings. - - """ + Runs eDisGo with the desired settings. + + """ logger.info('Calculating interface values') - + specs = get_etragospecs_direct( - session, - bus_id, - etrago_network, - scn_name) - + session, + bus_id, + etrago_network, + scn_name) + ding0_filepath = ( - ding0_files - + '/ding0_grids__' - + str(mv_grid_id) - + '.pkl') + ding0_files + + '/ding0_grids__' + + str(mv_grid_id) + + '.pkl') if not os.path.isfile(ding0_filepath): - msg = 'Not MV grid file for MV grid ID: ' + str(mv_grid_id) + msg = 'Not MV grid file for MV grid ID: ' + str(mv_grid_id) logger.error(msg) raise Exception(msg) - - + logger.info('Initial MV grid reinforcement (starting grid)') edisgo_grid, \ - costs_before_geno_import, \ - grid_issues_before_geno_import = run_edisgo_basic( + costs_before_geno_import, \ + grid_issues_before_geno_import = run_edisgo_basic( ding0_filepath=ding0_filepath, generator_scenario=None, analysis='worst-case') - + logger.info('eTraGo feed-in case') - + edisgo_grid.network.results = Results() - -# Generator Import is currently not working in eDisGo + +# Generator Import is currently not working in eDisGo # if self._generator_scn: # edisgo_grid.import_generators( # generator_scenario=self._generator_scn) - + print(specs['conv_dispatch']) - edisgo_grid.network.timeseries = TimeSeriesControl( - # Here, I use only normalized values from specs - timeseries_generation_fluctuating=specs['potential'], - timeseries_generation_dispatchable=specs['conv_dispatch'], - timeseries_load='demandlib', - config_data=edisgo_grid.network.config, - timeindex=specs['conv_dispatch'].index).timeseries - -# This will be used after the next eDisGo release + edisgo_grid.network.timeseries = TimeSeriesControl( + # Here, I use only normalized values from specs + timeseries_generation_fluctuating=specs['potential'], + timeseries_generation_dispatchable=specs['conv_dispatch'], + timeseries_load='demandlib', + config_data=edisgo_grid.network.config, + timeindex=specs['conv_dispatch'].index).timeseries + +# This will be used after the next eDisGo release # update_pypsa_timeseries( -# edisgo_grid.network, -# timesteps=specs['conv_dispatch'].index) - +# edisgo_grid.network, +# timesteps=specs['conv_dispatch'].index) + logger.warning('Curtailment can only be included after gen import') # edisgo_grid.curtail(curtailment_methodology='curtail_all', # # Here, I use absolute values -# timeseries_curtailment=specs['curtailment_abs']) -# +# timeseries_curtailment=specs['curtailment_abs']) +# # # Think about the other curtailment functions!!!! - + # This will become unnecessary with the next eDisGo release - edisgo_grid.network.pypsa = None + edisgo_grid.network.pypsa = None edisgo_grid.analyze() - - edisgo_grid.reinforce() + + edisgo_grid.reinforce() # Get costs costs_grouped = \ @@ -287,13 +282,13 @@ def run_edisgo( index=[[edisgo_grid.network.id] * len(costs_grouped), costs_grouped.index]).reset_index() costs.rename(columns={'level_0': 'grid'}, inplace=True) - + # Grid issues besser verstehen!! Und evtl. mit aussgeben print(costs) return edisgo_grid - - -## Helpful tools + + +# Helpful tools def get_mv_grid_from_bus_id(self, bus_id): """ Returns the MV grid ID for a given eTraGo bus @@ -302,27 +297,27 @@ def get_mv_grid_from_bus_id(self, bus_id): if self._versioned is True: ormclass_hvmv_subst = grid.__getattribute__( - 'EgoDpHvmvSubstation' - ) + 'EgoDpHvmvSubstation' + ) subst_id = self._session.query( - ormclass_hvmv_subst.subst_id - ).filter( - ormclass_hvmv_subst.otg_id == bus_id, - ormclass_hvmv_subst.version == self._grid_version - ).scalar() + ormclass_hvmv_subst.subst_id + ).filter( + ormclass_hvmv_subst.otg_id == bus_id, + ormclass_hvmv_subst.version == self._grid_version + ).scalar() if self._versioned is False: ormclass_hvmv_subst = model_draft.__getattribute__( - 'EgoGridHvmvSubstation' - ) + 'EgoGridHvmvSubstation' + ) subst_id = self._session.query( - ormclass_hvmv_subst.subst_id - ).filter( - ormclass_hvmv_subst.otg_id == bus_id - ).scalar() - + ormclass_hvmv_subst.subst_id + ).filter( + ormclass_hvmv_subst.otg_id == bus_id + ).scalar() + return subst_id - + def get_bus_id_from_mv_grid(self, subst_id): """ Returns the eTraGo bus ID for a given MV grid @@ -330,28 +325,26 @@ def get_bus_id_from_mv_grid(self, subst_id): """ if self._versioned is True: ormclass_hvmv_subst = grid.__getattribute__( - 'EgoDpHvmvSubstation' - ) + 'EgoDpHvmvSubstation' + ) bus_id = self._session.query( - ormclass_hvmv_subst.otg_id - ).filter( - ormclass_hvmv_subst.subst_id == subst_id, - ormclass_hvmv_subst.version == self._grid_version - ).scalar() + ormclass_hvmv_subst.otg_id + ).filter( + ormclass_hvmv_subst.subst_id == subst_id, + ormclass_hvmv_subst.version == self._grid_version + ).scalar() if self._versioned is False: ormclass_hvmv_subst = model_draft.__getattribute__( - 'EgoGridHvmvSubstation' - ) + 'EgoGridHvmvSubstation' + ) bus_id = self._session.query( - ormclass_hvmv_subst.otg_id - ).filter( - ormclass_hvmv_subst.subst_id == subst_id - ).scalar() - - return bus_id + ormclass_hvmv_subst.otg_id + ).filter( + ormclass_hvmv_subst.subst_id == subst_id + ).scalar() + + return bus_id def get_hvmv_translation(self): raise NotImplementedError - - From 65bc7d60100f2f50e7d60eda0ff5de2dd9a9c594 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 13:37:54 +0200 Subject: [PATCH 251/314] update docu --- doc/_static/ribbons.html | 1 + doc/images/open_ego_logo.png | Bin 0 -> 58224 bytes doc/index.rst | 15 +++++++++++---- doc/installation.rst | 6 +++--- 4 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 doc/_static/ribbons.html create mode 100644 doc/images/open_ego_logo.png diff --git a/doc/_static/ribbons.html b/doc/_static/ribbons.html new file mode 100644 index 00000000..1bc61e26 --- /dev/null +++ b/doc/_static/ribbons.html @@ -0,0 +1 @@ + diff --git a/doc/images/open_ego_logo.png b/doc/images/open_ego_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..3e34fccc63859add51386ec0ebf725a18eb6db31 GIT binary patch literal 58224 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 CER!(+ literal 0 HcmV?d00001 diff --git a/doc/index.rst b/doc/index.rst index e3511a47..9936f91d 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -2,9 +2,14 @@ Welcome to eGo documentation! ============================= -.. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 + + +.. image:: images/open_ego_logo.png :align: right - :scale: 100% + :scale: 40% + + + .. note:: Note, this software is under construction and not ready for a normal use. @@ -15,6 +20,9 @@ Welcome to eGo documentation! `openenergy-platform.org/login `_. +Overview +======== + .. toctree:: :maxdepth: 2 @@ -43,5 +51,4 @@ Indices and tables .. raw:: html - Fork me on GitHub - + :file: _static/ribbons.html diff --git a/doc/installation.rst b/doc/installation.rst index 5d91ac6b..48717561 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -73,7 +73,7 @@ access / login data will be saved in the folder ``.egoio`` in the file oedialect connection -------------------- -.. code-block:: desktop +.. code-block:: bash [oedb] dialect = oedialect @@ -87,7 +87,7 @@ oedialect connection Local database connection ------------------------- -.. code-block:: desktop +.. code-block:: bash [local] username = YourOEDBUserName @@ -101,7 +101,7 @@ Local database connection Old developer connection ------------------------ -.. code-block:: desktop +.. code-block:: bash [oedb] username = YourOEDBUserName From 52f4a868c57d39d7ea554c627e776d87c99d727a Mon Sep 17 00:00:00 2001 From: maltesc Date: Tue, 17 Jul 2018 13:38:22 +0200 Subject: [PATCH 252/314] eDisGo integration including curtailment --- ego/scenario_setting.json | 4 +- ego/tools/economics.py | 52 ++++++++++++--------- ego/tools/edisgo_integration.py | 83 ++++++++++++++++----------------- ego/tools/io.py | 16 ++++--- ego/tools/specs.py | 81 ++++++++++++++++++-------------- 5 files changed, 127 insertions(+), 109 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 6092eaf7..d37ddaa2 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -4,7 +4,7 @@ "eDisGo": true, "db": "oedb", "result_id": 26, - "recover": false, + "recover": true, "gridversion": "v0.4.2" }, "eTraGo": { @@ -45,7 +45,7 @@ "ding0_files": "data/MV_grids/20180713110719", "choice_mode": "manual", "no_grids": null, - "manual_grids": [1729, 1730, 1731, 1732, 1733], + "manual_grids": [1729], "scn_name": "NEP 2035", "comments": "make a comment" } diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 765cef76..4b1a4e50 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -66,16 +66,13 @@ def annuity_per_period(capex, n, wacc, t, p): # cost_config = {"p": 0.04} -def edisgo_convert_capital_costs(grid_components, cost_config, json_file): +def edisgo_convert_capital_costs(overnight_cost, t, p, json_file): """ Get scenario and calculation specific annuity cost by given capital costs and lifetime. Parameters ---------- - grid_components : :obj:dict - Dictionary of ding0 grid components which are extendable - (Name, investment_cost, lifetime) json_file : :obj:dict Dictionary of the ``scenario_setting.json`` file _start_snapshot : int @@ -103,11 +100,9 @@ def edisgo_convert_capital_costs(grid_components, cost_config, json_file): # Based on eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 - T = 40 # from grid_components ? - p = cost_config['p'] - + # Calculate present value of an annuity (PVA) - PVA = (1 / p) - (1 / (p*(1 + p) ** T)) + PVA = (1 / p) - (1 / (p*(1 + p) ** t)) year = 8760 # get period of calculation @@ -115,7 +110,7 @@ def edisgo_convert_capital_costs(grid_components, cost_config, json_file): - json_file['eTraGo']['start_snapshot']) # calculation of capital_cost - annuity_cost = (capital_cost / (PVA * (year/(period+1)))) + annuity_cost = (overnight_cost / (PVA * (year/(period+1)))) return annuity_cost @@ -258,7 +253,7 @@ def v_level(lines): -def edisgo_grid_investment(edisgo_networks): +def edisgo_grid_investment(edisgo_networks, json_file): """Function to get all costs of grid investment of eDisGo. Parameters @@ -269,30 +264,43 @@ def edisgo_grid_investment(edisgo_networks): """ - + t = 40 - p=0.05 + p = 0.05 logger.warning('For all components T={} and p={} is used'.format(t, p)) - capital_costs = pd.DataFrame(columns=['v_lev', 'capital_costs']) + annuity_costs = pd.DataFrame(columns=['v_lev', 'annuity_costs']) for key, value in edisgo_networks.edisgo_grids.items(): - costs_grouped = value.network.results.grid_expansion_costs - costs_grouped.to_csv('test.csv') - costs_grouped = costs_grouped.rename( + costs_single = value.network.results.grid_expansion_costs + + costs_single = costs_single.rename( columns={'voltage_level': 'v_lev'} ) - - costs_grouped['capital_costs'] = test(costs_grouped['total_costs']) + choice = edisgo_networks.grid_choice + weighting = choice.loc[ + choice['the_selected_network_id'] == key + ][ + 'no_of_points_per_cluster' + ].values[0] + + costs_single['annuity_costs'] = edisgo_convert_capital_costs( + costs_single['total_costs'], + t=t, + p=p, + json_file=json_file) + + costs_single['annuity_costs'] = ( + costs_single['annuity_costs'] * weighting) - costs_grouped = costs_grouped[['v_lev', 'capital_costs']] + costs_single = costs_single[['v_lev', 'annuity_costs']] - capital_costs = capital_costs.append(costs_grouped, ignore_index=True) + annuity_costs = annuity_costs.append(costs_single, ignore_index=True) - aggr_capital_costs = capital_costs.groupby(['v_lev']).sum().reset_index() + aggr_capital_costs = annuity_costs.groupby(['v_lev']).sum().reset_index() aggr_capital_costs = aggr_capital_costs.rename( - columns={'capital_costs': 'grid_costs'} + columns={'annuity_costs': 'grid_costs'} ) aggr_capital_costs['grid_costs'] = aggr_capital_costs['grid_costs'] * 1000 diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 29b24c04..e3aad293 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -21,6 +21,7 @@ run_edisgo_basic, run_edisgo_pool_flexible ) +from edisgo.grid import tools from ego.tools.specs import ( get_etragospecs_direct, # get_feedin_fluctuating, @@ -94,6 +95,14 @@ def edisgo_grids(self): """ return self._edisgo_grids + + @property + def grid_choice(self): + """ + Returns the chosen grids + + """ + return self._grid_choice # @property # def edisgo_costs(self): @@ -230,16 +239,15 @@ def _run_edisgo(self, mv_grid_id): """ -# logger.info('Calculating interface values') -# -# bus_id = self._get_bus_id_from_mv_grid(mv_grid_id) -# -# specs = get_etragospecs_direct( -# self._session, -# bus_id, -# self._etrago_network, -# self._scn_name) + logger.info('Calculating interface values') + bus_id = self._get_bus_id_from_mv_grid(mv_grid_id) + specs = get_etragospecs_direct( + self._session, + bus_id, + self._etrago_network, + self._scn_name) + ding0_filepath = ( self._ding0_files + '/ding0_grids__' @@ -256,15 +264,11 @@ def _run_edisgo(self, mv_grid_id): ding0_filepath=ding0_filepath, generator_scenario=None, analysis='worst-case')[0] # only the edisgo_grid is returned - - logger.warning('Function not fully executed!!') - return edisgo_grid - - logger.info('eTraGo feed-in case') - + + + logger.info('eTraGo feed-in case') edisgo_grid.network.results = Results() - -# Generator Import is currently not working in eDisGo + if self._generator_scn: logger.info( 'Importing generators for scenario {}'.format( @@ -273,45 +277,38 @@ def _run_edisgo(self, mv_grid_id): edisgo_grid.import_generators( generator_scenario=self._generator_scn) - edisgo_grid.network.timeseries = TimeSeriesControl( network=edisgo_grid.network, # Here, I use only normalized values from specs timeseries_generation_fluctuating=specs['potential'], timeseries_generation_dispatchable=specs['conv_dispatch'], timeseries_load='demandlib', -# config_data=edisgo_grid.network.config, timeindex=specs['conv_dispatch'].index).timeseries - - # This will be used after the next eDisGo release - # update_pypsa_timeseries( - # edisgo_grid.network, - # timesteps=specs['conv_dispatch'].index) + + logger.info('Including Curtailment') + gens_df = tools.get_gen_info(edisgo_grid.network) + solar_wind_capacities = gens_df.groupby(by=['type', 'weather_cell_id'])[ + 'nominal_capacity'].sum() - logger.warning('Curtailment can only be included after gen import') - # edisgo_grid.curtail(curtailment_methodology='curtail_all', - # # Here, I use absolute values - # timeseries_curtailment=specs['curtailment_abs']) - # - # # Think about the other curtailment functions!!!! + curt_abs = pd.DataFrame(columns=specs['curtailment'].columns) + + for col in curt_abs: + curt_abs[col] = ( + specs['curtailment'][col] + * solar_wind_capacities[col]) - # This will become unnecessary with the next eDisGo release -# + curt_abs = curt_abs * 0.999 + logger.warning('Curtailment reduced to 99.9 %') + + edisgo_grid.curtail(curtailment_methodology='curtail_all', + # Here, I use absolute values + timeseries_curtailment=curt_abs) +# Think about the other curtailment functions!!!! + edisgo_grid.analyze() edisgo_grid.reinforce() -# # Get costs -# costs_grouped = \ -# edisgo_grid.network.results.grid_expansion_costs.groupby( -# ['type']).sum() -# costs = pd.DataFrame(costs_grouped.values, -# columns=costs_grouped.columns, -# index=[[edisgo_grid.network.id] * len(costs_grouped), -# costs_grouped.index]).reset_index() -# costs.rename(columns={'level_0': 'grid'}, inplace=True) - - # Grid issues besser verstehen!! Und evtl. mit aussgeben return edisgo_grid diff --git a/ego/tools/io.py b/ego/tools/io.py index 1f2bce4c..03d1d673 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -43,9 +43,12 @@ EgoGridPfHvTempResolution as TempResolution from tools.results import (create_etrago_results) from tools.storages import (total_storage_charges, etrago_storages) - from tools.economics import (etrago_operating_costs, etrago_grid_investment, - edisgo_grid_investment, investment_costs, - get_generator_investment) + from tools.economics import ( + etrago_operating_costs, + etrago_grid_investment, + edisgo_grid_investment, + investment_costs, + get_generator_investment) from tools.utilities import get_scenario_setting, get_time_steps from tools.edisgo_integration import EDisGoNetworks from egoio.db_tables.model_draft import RenpassGisParameterRegion @@ -313,9 +316,10 @@ def __init__(self, jsonpath, *args, **kwargs): json_file=self.json_file, etrago_network=self.etrago_network) - def edisgo_total_costs(self, **kwargs): - - return df + self.edisgo.grid_costs = edisgo_grid_investment( + self.edisgo_networks, + self.json_file + ) class eGo(eDisGoResults): diff --git a/ego/tools/specs.py b/ego/tools/specs.py index 402c6145..95449eab 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -542,7 +542,7 @@ def get_etragospecs_direct(session, aggr_gens['ren_id'] = aggr_gens.index -# print(aggr_gens) + print(aggr_gens) ### Dispatch and Curteilment potential = pd.DataFrame(0.0, @@ -582,21 +582,30 @@ def get_etragospecs_direct(session, p_norm_tot_series = p_series / p_nom_aggr p_max_pu_series = etrago_network.generators_t.p_max_pu[str(gen_id)] - p_max_series = p_max_pu_series * p_nom +# p_max_series = p_max_pu_series * p_nom p_max_norm_tot_series = p_max_pu_series * p_nom / p_nom_aggr - p_curt_tot_series = p_max_series - p_series - p_curt_norm_tot_series = p_max_norm_tot_series - p_norm_tot_series - +# p_curt_tot_series = p_max_series - p_series +# p_curt_norm_tot_series = p_max_norm_tot_series - p_norm_tot_series + + + potential[ren_id] = potential[ren_id] + p_max_norm_tot_series dispatch[ren_id] = dispatch[ren_id] + p_norm_tot_series - curtailment[ren_id] = curtailment[ren_id] + p_curt_norm_tot_series +# curtailment[ren_id] = curtailment[ren_id] + p_curt_norm_tot_series + + potential = potential.round(3) + dispatch = dispatch.round(3) + + logger.warning('Rounding normalized values') + curtailment = potential.sub(dispatch) + - potential_abs[ren_id] = potential_abs[ren_id] + p_max_series - dispatch_abs[ren_id] = dispatch_abs[ren_id] + p_series - curtailment_abs[ren_id] = curtailment_abs[ren_id] + p_curt_tot_series +# potential_abs[ren_id] = potential_abs[ren_id] + p_max_series +# dispatch_abs[ren_id] = dispatch_abs[ren_id] + p_series +# curtailment_abs[ren_id] = curtailment_abs[ren_id] + p_curt_tot_series - potential = dispatch + curtailment +# potential = dispatch + curtailment new_columns = [ (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], @@ -616,27 +625,27 @@ def get_etragospecs_direct(session, for col in curtailment.columns] curtailment.columns = pd.MultiIndex.from_tuples(new_columns) - new_columns = [ - (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], - aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) - for col in potential_abs.columns] - potential_abs.columns = pd.MultiIndex.from_tuples(new_columns) - - new_columns = [ - (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], - aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) - for col in dispatch_abs.columns] - dispatch_abs.columns = pd.MultiIndex.from_tuples(new_columns) - - new_columns = [ - (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], - aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) - for col in curtailment_abs.columns] - curtailment_abs.columns = pd.MultiIndex.from_tuples(new_columns) - - potential_abs = potential_abs * 1000 - dispatch_abs = dispatch_abs * 1000 - curtailment_abs = curtailment_abs * 1000 +# new_columns = [ +# (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], +# aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) +# for col in potential_abs.columns] +# potential_abs.columns = pd.MultiIndex.from_tuples(new_columns) +# +# new_columns = [ +# (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], +# aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) +# for col in dispatch_abs.columns] +# dispatch_abs.columns = pd.MultiIndex.from_tuples(new_columns) +# +# new_columns = [ +# (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], +# aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) +# for col in curtailment_abs.columns] +# curtailment_abs.columns = pd.MultiIndex.from_tuples(new_columns) +# +# potential_abs = potential_abs * 1000 # Absolute amounts in kW +# dispatch_abs = dispatch_abs * 1000 +# curtailment_abs = curtailment_abs * 1000 # Storage t3 = time.perf_counter() @@ -705,14 +714,14 @@ def get_etragospecs_direct(session, # 'battery_capacity': battery_capacity, # 'battery_active_power': battery_active_power, 'conv_dispatch': conv_dsptch_norm, - 'conv_dispatch_abs': conv_dsptch_abs, +# 'conv_dispatch_abs': conv_dsptch_abs, # 'renewables': aggr_gens, 'dispatch': dispatch, - 'dispatch_abs': dispatch_abs, +# 'dispatch_abs': dispatch_abs, 'potential': potential, - 'potential_abs': potential_abs, - 'curtailment': curtailment, - 'curtailment_abs': curtailment_abs +# 'potential_abs': potential_abs, + 'curtailment': curtailment#, +# 'curtailment_abs': curtailment_abs } # specs = ETraGoSpecs(battery_capacity=battery_capacity, From 8e6f1d5bef507d4e094b955f849dadff761ba4ab Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 13:49:45 +0200 Subject: [PATCH 253/314] add rtd clause --- ego/tools/edisgo_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index f3a2edff..6b79dd54 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -13,6 +13,7 @@ # Local Packages # Project Packages +import os if not 'READTHEDOCS' in os.environ: from egoio.db_tables import model_draft, grid from egoio.tools import db @@ -33,7 +34,6 @@ from ego.tools.utilities import define_logging # Other Packages -import os import logging import multiprocessing as mp import pandas as pd From f844ebaaac2710158bf2d2fb894b16c2ef1f7722 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 14:04:17 +0200 Subject: [PATCH 254/314] update docu --- ego/tools/edisgo_integration.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 6b79dd54..cb08b3f1 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -1,19 +1,37 @@ +# -*- coding: utf-8 -*- +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# File description """ This file is part of the the eGo toolbox. It contains the class definition for multiple eDisGo networks and results. - """ __copyright__ = ("Flensburg University of Applied Sciences, " "Europa-Universität Flensburg, " "Centre for Sustainable Energy Systems") __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolf_bunke,maltesc" +__author__ = "wolf_bunke, maltesc" # Import # Local Packages # Project Packages -import os +#import os if not 'READTHEDOCS' in os.environ: from egoio.db_tables import model_draft, grid from egoio.tools import db From 29b688f75aa7abacee49452d31a596fe26d2b16f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 14:04:56 +0200 Subject: [PATCH 255/314] update docu --- ego/tools/mv_cluster.py | 277 +++++++++++++++++++++++----------------- 1 file changed, 158 insertions(+), 119 deletions(-) diff --git a/ego/tools/mv_cluster.py b/ego/tools/mv_cluster.py index 46ee72c0..9cb39644 100644 --- a/ego/tools/mv_cluster.py +++ b/ego/tools/mv_cluster.py @@ -1,9 +1,24 @@ -#!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" -Created on Thu Apr 19 09:50:36 2018 +# Copyright 2016-2018 Europa-Universität Flensburg, +# Flensburg University of Applied Sciences, +# Centre for Sustainable Energy Systems +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . -@author: student +# File description +""" +Make MV Cluster """ from __future__ import print_function @@ -18,124 +33,144 @@ from mpl_toolkits.mplot3d import Axes3D import matplotlib.cm as cm + def analyze_attributes(ding0_files): base_path = ding0_files - + not_found = [] - tccs = [] # Total Cumulative Capacity of Solar - tccw = [] # Total Cumulative Capacity of Wind - fnlvmv = [] # the Farthest Node in both networks (lv and mv) - MV_id_list = [] # Distrct id list - - for district_number in list(range(1,4000)): # 3608 MVGDs - + tccs = [] # Total Cumulative Capacity of Solar + tccw = [] # Total Cumulative Capacity of Wind + fnlvmv = [] # the Farthest Node in both networks (lv and mv) + MV_id_list = [] # Distrct id list + + for district_number in list(range(1, 4000)): # 3608 MVGDs + # To bypass not found error try: - pickle_name = 'ding0_grids__{}.pkl'.format(district_number) # To open the pickle files - nd = pickle.load(open(os.path.join(base_path, pickle_name), 'rb')) # assign the data to a variable + pickle_name = 'ding0_grids__{}.pkl'.format( + district_number) # To open the pickle files + # assign the data to a variable + nd = pickle.load(open(os.path.join(base_path, pickle_name), 'rb')) print('District no.', district_number, 'found!') except: - not_found.append(district_number) # append not found network files id to a list - #print('District no.', district_number, 'NOT found') # print not found ids + # append not found network files id to a list + not_found.append(district_number) + # print('District no.', district_number, 'NOT found') # print not found ids continue - + MV_id = 0 MV_id = nd._mv_grid_districts[0].id_db - - mv_cum_solar_MV = 0 # Solar cumulative capacity in MV - mv_cum_wind_MV = 0 # Solar cumulative capacity in MV - + + mv_cum_solar_MV = 0 # Solar cumulative capacity in MV + mv_cum_wind_MV = 0 # Solar cumulative capacity in MV + # cumulative capacity of solar and wind in MV for geno in nd._mv_grid_districts[0].mv_grid.generators(): if geno.type == 'solar': mv_cum_solar_MV += geno.capacity if geno.type == 'wind': mv_cum_wind_MV += geno.capacity - + lvg = 0 # lvg_type = [] # counter_lv = [{}] mv_cum_solar_LV = 0 mv_cum_wind_LV = 0 - + # cumulative capacity of solar and wind in LV for lvgs in nd._mv_grid_districts[0].lv_load_areas(): for lvgs1 in lvgs.lv_grid_districts(): - lvg += len(list(lvgs1.lv_grid.generators())) # No. of DGs in lv + lvg += len(list(lvgs1.lv_grid.generators())) # No. of DGs in lv for deno in lvgs1.lv_grid.generators(): if deno.type == 'solar': mv_cum_solar_LV += deno.capacity if deno.type == 'wind': mv_cum_wind_LV += deno.capacity - - total_cum_solar = mv_cum_solar_MV + mv_cum_solar_LV # Total solar cumulative capacity in lv and mv - total_cum_wind = mv_cum_wind_MV + mv_cum_wind_LV # Total wind cumulative capacity in lv and mv - + + # Total solar cumulative capacity in lv and mv + total_cum_solar = mv_cum_solar_MV + mv_cum_solar_LV + # Total wind cumulative capacity in lv and mv + total_cum_wind = mv_cum_wind_MV + mv_cum_wind_LV + # append to lists tccs.append(total_cum_solar) tccw.append(total_cum_wind) - + # The farthest node length from MV substation from ding0.core.network.stations import LVStationDing0 - + tot_dist = [] max_length = 0 max_length_list = [] max_of_max = 0 - - nd.control_circuit_breakers(mode='open') # make CB open (normal operation case) - root_mv = nd._mv_grid_districts[0].mv_grid.station() # setting the root to measure the path from + + # make CB open (normal operation case) + nd.control_circuit_breakers(mode='open') + # setting the root to measure the path from + root_mv = nd._mv_grid_districts[0].mv_grid.station() # 1st from MV substation to LV station node - for node2 in nd._mv_grid_districts[0].mv_grid._graph.nodes(): # Iteration through nodes - if isinstance(node2, LVStationDing0) and not node2.lv_load_area.is_aggregated: # select only LV station nodes - + # Iteration through nodes + for node2 in nd._mv_grid_districts[0].mv_grid._graph.nodes(): + # select only LV station nodes + if isinstance(node2, LVStationDing0) and not node2.lv_load_area.is_aggregated: + length_from_MV_to_LV_station = 0 # Distance from MV substation to LV station node - length_from_MV_to_LV_station = nd._mv_grid_districts[0].mv_grid.graph_path_length(node_source=node2,node_target=root_mv) / 1000 + length_from_MV_to_LV_station = nd._mv_grid_districts[0].mv_grid.graph_path_length( + node_source=node2, node_target=root_mv) / 1000 # 2nd from LV station node to the longest distance node - - for lvgs in nd._mv_grid_districts[0].lv_load_areas(): # Iteration through lv load areas - for lvgs1 in lvgs.lv_grid_districts(): # Iteration through lv grid districts + + # Iteration through lv load areas + for lvgs in nd._mv_grid_districts[0].lv_load_areas(): + for lvgs1 in lvgs.lv_grid_districts(): # Iteration through lv grid districts # In order to measure the distance between the LV station and the nodes that belong to it and not from other stations if lvgs1.lv_grid._station == node2: - root_lv = node2 # setting a new root - for node1 in lvgs1.lv_grid._graph.nodes(): # iteration of all nodes in LV grid - - length_from_LV_staion_to_LV_node = 0 - # Distance from LV station to LV nodes - length_from_LV_staion_to_LV_node = lvgs1.lv_grid.graph_path_length(node_source=node1,node_target=root_lv) / 1000 - - length_from_LV_node_to_MV_substation = 0 - # total distances in both grids MV and LV - length_from_LV_node_to_MV_substation = length_from_MV_to_LV_station + length_from_LV_staion_to_LV_node - - tot_dist.append(length_from_LV_node_to_MV_substation) # append the total distance to a list - if any(tot_dist): # to make sure the list is not empty - max_length = max(tot_dist) # to pick up the max length within this grid - max_length_list.append(max_length) # append max lengths of all grids to a list - if any(max_length_list): # to make sure the list is not empty - max_of_max = max(max_length_list) # to pick up max of max - - fnlvmv.append(max_of_max) # append to a new list - MV_id_list.append(MV_id) # append the network id to a new list - + root_lv = node2 # setting a new root + for node1 in lvgs1.lv_grid._graph.nodes(): # iteration of all nodes in LV grid + + length_from_LV_staion_to_LV_node = 0 + # Distance from LV station to LV nodes + length_from_LV_staion_to_LV_node = lvgs1.lv_grid.graph_path_length( + node_source=node1, node_target=root_lv) / 1000 + + length_from_LV_node_to_MV_substation = 0 + # total distances in both grids MV and LV + length_from_LV_node_to_MV_substation = length_from_MV_to_LV_station + \ + length_from_LV_staion_to_LV_node + + # append the total distance to a list + tot_dist.append( + length_from_LV_node_to_MV_substation) + if any(tot_dist): # to make sure the list is not empty + # to pick up the max length within this grid + max_length = max(tot_dist) + # append max lengths of all grids to a list + max_length_list.append(max_length) + if any(max_length_list): # to make sure the list is not empty + # to pick up max of max + max_of_max = max(max_length_list) + + fnlvmv.append(max_of_max) # append to a new list + MV_id_list.append(MV_id) # append the network id to a new list + # export results to dataframes - d = {'id': MV_id_list,'Solar_cumulative_capacity': tccs, + d = {'id': MV_id_list, 'Solar_cumulative_capacity': tccs, 'Wind_cumulative_capacity': tccw, - 'The_Farthest_node': fnlvmv} # assign lists to columns + 'The_Farthest_node': fnlvmv} # assign lists to columns # not founded networks are_not_found = {'District_files_that_are_not_found': not_found} - - df = pd.DataFrame(d) # dataframe for results - - df_are_not_found = pd.DataFrame(are_not_found) # dataframe for not found files id - + + df = pd.DataFrame(d) # dataframe for results + + # dataframe for not found files id + df_are_not_found = pd.DataFrame(are_not_found) + # Exporting dataframe to CSV files df.to_csv(base_path + '/' + 'attributes.csv', sep=',') df_are_not_found.to_csv(base_path + '/' + 'Not_found_grids.csv', sep=',') - - ##3d scatter plotting + + # 3d scatter plotting #from mpl_toolkits.mplot3d import Axes3D #import matplotlib.pyplot as plt # @@ -156,130 +191,134 @@ def analyze_attributes(ding0_files): #ax.set_ylabel('\nWind cumulative capacity (MW)', linespacing=2) #ax.set_zlabel('\nThe farthest node (km)', linespacing=2) # - #plt.show() - + # plt.show() + def cluster_mv_grids(ding0_files, no_grids): - + # import CSV data file that exported from Networks_analysis_solar_wind_farthest-node.py and assign it to a data frame df = pd.read_csv(ding0_files + '/attributes.csv') - + # extract each column to a variable - x = df.Solar_cumulative_capacity # Solar capacity in MV and LV - y = df.Wind_cumulative_capacity # Wind capacity in MV and LV - z = df.The_Farthest_node # The farthest node (the length between HV/MV substation to the farthest node in LV networks) - id_ = df.id # Network id - + x = df.Solar_cumulative_capacity # Solar capacity in MV and LV + y = df.Wind_cumulative_capacity # Wind capacity in MV and LV + # The farthest node (the length between HV/MV substation to the farthest node in LV networks) + z = df.The_Farthest_node + id_ = df.id # Network id + # Addressing the max value of each column max_solar = max(x) max_wind = max(y) max_farthest = max(z) - + # Converting data to perunit scale solar_pu = x / max_solar wind_pu = y / max_wind distances_pu = z / max_farthest - + # Converting from vectors to coordinates array m = [] for r, s, t in zip(solar_pu, wind_pu, distances_pu): f = [r, s, t] m.append(f) X = np.array(m) - + # Initialize KMeans clustering by Sklearn pkg - no_clusters = no_grids # no. of clusters - + no_clusters = no_grids # no. of clusters + # random state should be given in order to have same results with every run of the script # it acts as a seed where the algorihm define the starting clustering point, 1808 shows good results ran_state = 1808 - + # Starting KMeans clustering - kmeans = KMeans(n_clusters=no_clusters,random_state=ran_state) - + kmeans = KMeans(n_clusters=no_clusters, random_state=ran_state) + # Return a label for each point which indicates to which cluster each point is assigned cluster_labels = kmeans.fit_predict(X) - + # Centers of clusters centroids = kmeans.cluster_centers_ - + id_clus_dist = {} - + # Iterate through each point in dataset array X for i in range(len(X)): - clus = cluster_labels[i] # point's cluster id - cent = centroids[cluster_labels[i]] # Cluster's center coordinates - + clus = cluster_labels[i] # point's cluster id + cent = centroids[cluster_labels[i]] # Cluster's center coordinates + # Distance from that point to cluster's center (3d coordinates) - dist = ((X[i][0] - centroids[clus][0]) ** 2 + (X[i][1] - centroids[clus][1]) ** 2 + (X[i][2] - centroids[clus][2]) ** 2) ** (1 / 2) - + dist = ((X[i][0] - centroids[clus][0]) ** 2 + (X[i][1] - centroids[clus] + [1]) ** 2 + (X[i][2] - centroids[clus][2]) ** 2) ** (1 / 2) + # three results are appended to a list (cluster's id, point's (MVGD) id and distance from that point to cluster's center) #id_clus_dist = [clus, id_[i], dist] - #list_id_clus_dist.append(id_clus_dist) - + # list_id_clus_dist.append(id_clus_dist) + # three results are appended to a dictionary (cluster's id, point's (MVGD) id and distance from that point to cluster's center) id_clus_dist.setdefault(clus, []).append({id_[i]: dist}) - + cluster_id = [] cluster_points = [] clus_percentage = [] closest_point = [] - - #Iterating through the clusters dictionary (key represents cluster's id , value represents another disctionary with network's id and distance of that point to cluster's center) + + # Iterating through the clusters dictionary (key represents cluster's id , value represents another disctionary with network's id and distance of that point to cluster's center) for key, value in id_clus_dist.items(): - no_points_clus = sum(1 for v in value if v) # How many points/cluster - clus_perc = (no_points_clus / len(X)) * 100 # percentage of points per cluster - + no_points_clus = sum(1 for v in value if v) # How many points/cluster + # percentage of points per cluster + clus_perc = (no_points_clus / len(X)) * 100 + # in the last dict "id_clus_dist" each key (cluster's id) has several dicts that contain information of network's id and distance, # the below code just to split the sub dicts and merge them as items in anothe single dict id_dist = {} for value_1 in value: id_dist.update(value_1) - + # returns the shortest distance point (selected network) to cluster's center short_dist_net_id_dist = min(id_dist.items(), key=lambda x: x[1]) - + # Exporting CSV sheet for every cluster that contains the assigned points (networks) and siatance from each to cluster's center daf = pd.DataFrame() daf['Network_id'] = id_dist.keys() daf['Distance_to_cluster_center'] = id_dist.values() # daf.to_csv('Cluster_No_{}.csv'.format(key), sep=',') - + # export to lists - cluster_id.append(key) # cluster id - cluster_points.append(no_points_clus) # No of points / cluster - clus_percentage.append(round(clus_perc,2)) # Percentage of points per cluster, # round(), two digits after comma - + cluster_id.append(key) # cluster id + cluster_points.append(no_points_clus) # No of points / cluster + # Percentage of points per cluster, # round(), two digits after comma + clus_percentage.append(round(clus_perc, 2)) + # the nearest point to cluster center (represented network), there is [0] because it is a tuple closest_point.append(short_dist_net_id_dist[0]) - + # exporting results to CSV file that contains cluster's id, the no. of assigned points (networks) and the selected network d = {'CLuster_id': cluster_id, 'no_of_points_per_cluster': cluster_points, 'cluster_percentage': clus_percentage, 'the_selected_network_id': closest_point} df = pd.DataFrame(d) # df.to_csv('Selected_networks_{}_clusters_dec.csv'.format(no_clusters), sep=',') - + return df - + # # Initiation of 3d graph for scattering plot # fig = plt.figure() # fig.suptitle('KMeans clustering', fontsize=20) # ax = fig.add_subplot(111, projection='3d') -# +# # # 3d scatter Plot # colors = cm.spectral(cluster_labels.astype(float) / no_clusters) # ax.scatter(X[:, 0], X[:, 1], X[:, 2], alpha=0.3, c=colors) -# +# # # Clusters centers 3d scatter plot # ax.scatter(centroids[:, 0], centroids[:, 1], centroids[:, 2], marker='x', alpha=1, s=50, linewidths=5, zorder=10,c='r') -# +# # #limiting the axes scale # ax.set_xlim(0, 1) # ax.set_ylim(0, 1) # ax.set_zlim(0, 1) -# +# # # show 3d scatter clustering # plt.show() -# -# # as for this example where no. of clusters is 20, the results should show 21 CSV files (20 for clusters and 1 for the selected netorks) \ No newline at end of file +# +# # as for this example where no. of clusters is 20, the results should show 21 CSV files (20 for clusters and 1 for the selected netorks) From 5f7b8608e7124e479388884054bdba4e4a157108 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 14:10:29 +0200 Subject: [PATCH 256/314] update docu --- ego/tools/edisgo_integration.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index cb08b3f1..5827bf33 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -31,7 +31,8 @@ # Local Packages # Project Packages -#import os +import os +import logging if not 'READTHEDOCS' in os.environ: from egoio.db_tables import model_draft, grid from egoio.tools import db @@ -51,11 +52,12 @@ cluster_mv_grids) from ego.tools.utilities import define_logging -# Other Packages -import logging -import multiprocessing as mp -import pandas as pd -from sqlalchemy.orm import sessionmaker + # Other Packages + import logging + import multiprocessing as mp + import pandas as pd + from sqlalchemy.orm import sessionmaker + # Logging logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) From 77e15a2a912e9f4dae4e379087919a2715aae86f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 14:31:53 +0200 Subject: [PATCH 257/314] update investment of grids --- ego/tools/economics.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index e17fb9ad..60c9609b 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -97,8 +97,8 @@ def edisgo_convert_capital_costs(grid_components, cost_config, json_file): -------- .. math:: - PVA = \frac{\frac{1}{p_{rate}}}{(\frac{1}{p_{rate}}*(1 + \ - p_{rate})^{T_{Lifetime}})} + PVA = (1 / p) - (1 / (p*(1 + p)^T)) + """ # Based on eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 @@ -130,7 +130,7 @@ def etrago_operating_costs(network): Returns ------- - power_price : :class:`~.pd.DataFrame` + power_price : :pandas:`pandas.Dataframe` Examples -------- @@ -219,7 +219,7 @@ def etrago_grid_investment(network, json_file): if 'network' in json_file['eTraGo']['extendable']: lines = network.lines[['v_nom', 'capital_cost', 's_nom', - 's_nom_min', 's_nom_opt']] + 's_nom_min', 's_nom_opt']].reset_index() lines['s_nom_expansion'] = lines.s_nom_opt.subtract( lines.s_nom, axis='index') @@ -243,7 +243,8 @@ def etrago_grid_investment(network, json_file): # get costs of transfomers trafos = network.transformers[['v_nom0', 'v_nom1', 'capital_cost', - 's_nom_extendable', 's_nom', 's_nom_opt']] + 's_nom_extendable', 's_nom', + 's_nom_opt']].reset_index() trafos['s_nom_extendable'] = trafos.s_nom_opt.subtract( trafos.s_nom, axis='index') @@ -265,9 +266,10 @@ def etrago_grid_investment(network, json_file): # aggregate lines and trafo line = lines[['v_level', 'number_of_expansion', - 'grid_costs']].groupby('v_level').sum() + 'grid_costs']].groupby('v_level').sum().reset_index() + trafo = trafos[['v_level', 'number_of_expansion', - 'grid_costs']].groupby('v_level').sum() + 'grid_costs']].groupby('v_level').sum().reset_index() # merge trafos and line frames = [line, trafo] From b0f449b94fba0c9a4fe635d0aed9618631ec3fd9 Mon Sep 17 00:00:00 2001 From: maltesc Date: Tue, 17 Jul 2018 14:50:27 +0200 Subject: [PATCH 258/314] eDisGo integration with curtailment --- ego/scenario_setting.json | 2 +- ego/tools/specs.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index d37ddaa2..a289b6f9 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -45,7 +45,7 @@ "ding0_files": "data/MV_grids/20180713110719", "choice_mode": "manual", "no_grids": null, - "manual_grids": [1729], + "manual_grids": [1729, 1730, 1731, 1732, 1733], "scn_name": "NEP 2035", "comments": "make a comment" } diff --git a/ego/tools/specs.py b/ego/tools/specs.py index 95449eab..d3f47bfa 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -542,7 +542,7 @@ def get_etragospecs_direct(session, aggr_gens['ren_id'] = aggr_gens.index - print(aggr_gens) +# print(aggr_gens) ### Dispatch and Curteilment potential = pd.DataFrame(0.0, From 6d3d68ddf6234967e2e51569cc13e9337ab2e044 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 14:57:25 +0200 Subject: [PATCH 259/314] new settings --- ego/scenario_setting.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 6a649527..c7085fab 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -1,7 +1,7 @@ { "global": { "eTraGo": true, - "eDisGo": true, + "eDisGo": false, "db": "oedb", "result_id": 26, "recover": false, @@ -29,7 +29,7 @@ "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": false, + "network_clustering_kmeans": 100, "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, From c259c5937971a7b743c9f971fa498f78ebbd088d Mon Sep 17 00:00:00 2001 From: maltesc Date: Tue, 17 Jul 2018 15:58:16 +0200 Subject: [PATCH 260/314] Full integration finished --- ego/scenario_setting.json | 2 +- ego/tools/economics.py | 3 ++ ego/tools/edisgo_integration.py | 88 +++++++++++---------------------- 3 files changed, 34 insertions(+), 59 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index a289b6f9..f437ba07 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -45,7 +45,7 @@ "ding0_files": "data/MV_grids/20180713110719", "choice_mode": "manual", "no_grids": null, - "manual_grids": [1729, 1730, 1731, 1732, 1733], + "manual_grids": [1730], "scn_name": "NEP 2035", "comments": "make a comment" } diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 5afdca9b..09e5154a 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -300,6 +300,9 @@ def edisgo_grid_investment(edisgo_networks, json_file): for key, value in edisgo_networks.edisgo_grids.items(): costs_single = value.network.results.grid_expansion_costs + if not costs_single: + logger.warning('No results for grid {}'.format(key)) + continue costs_single = costs_single.rename( columns={'voltage_level': 'v_lev'} diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index efdc6935..a3143ca0 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -19,7 +19,7 @@ # File description """ This file is part of the the eGo toolbox. -It contains the class definition for multiple eDisGo networks and results. +It contains the class definition for multiple eDisGo networks. """ __copyright__ = ("Flensburg University of Applied Sciences, " "Europa-Universität Flensburg, " @@ -28,35 +28,23 @@ __author__ = "wolf_bunke, maltesc" # Import -# Local Packages - -# Project Packages import os import logging if not 'READTHEDOCS' in os.environ: from egoio.db_tables import model_draft, grid from egoio.tools import db from edisgo.grid.network import Results, TimeSeriesControl - #from edisgo.tools.pypsa_io import update_pypsa_timeseries from edisgo.tools.edisgo_run import ( - run_edisgo_basic, - run_edisgo_pool_flexible + run_edisgo_basic ) from edisgo.grid import tools from ego.tools.specs import ( - - get_etragospecs_direct, - # get_feedin_fluctuating, - # get_curtailment + get_etragospecs_direct ) from ego.tools.mv_cluster import ( analyze_attributes, cluster_mv_grids) - from ego.tools.utilities import define_logging - # Other Packages - import logging - import multiprocessing as mp import pandas as pd from sqlalchemy.orm import sessionmaker @@ -65,21 +53,27 @@ logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) logger = logging.getLogger('ego') - class EDisGoNetworks: """ - Represents multiple eDisGo networks. - + Performs multiple eDisGo runs and stores the resulting edisgo_grids + + Parameters + ---------- + json_file : :obj:dict + Dictionary of the ``scenario_setting.json`` file + etrago_network: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` + """ - def __init__(self, **kwargs): + def __init__(self, json_file, etrago_network): conn = db.connection(section='oedb') Session = sessionmaker(bind=conn) self._session = Session() # Json Inputs - self._json_file = kwargs.get('json_file', None) + self._json_file = json_file self._grid_version = self._json_file['global']['gridversion'] # eDisGo args @@ -101,19 +95,24 @@ def __init__(self, **kwargs): self._versioned = False # eTraGo - self._etrago_network = kwargs.get('etrago_network', None) + self._etrago_network = etrago_network + # eDisGo Results self._edisgo_grids = {} -# self._edisgo_costs = {} - ## Functions + ## Execute Functions self._set_grid_choice() self._run_edisgo_pool() @property def edisgo_grids(self): """ - Returns all calculated MV grids as dictionary + Container of + + Returns + ------- + :obj:`collections.OrderedDict` + Configuration data from config files. """ return self._edisgo_grids @@ -125,14 +124,6 @@ def grid_choice(self): """ return self._grid_choice - -# @property -# def edisgo_costs(self): -# """ -# Returns all calculated MV costs as dictionary -# -# """ -# return self._edisgo_costs def _analyze_cluster_attributes(self): """ @@ -209,19 +200,9 @@ def _run_edisgo_pool(self, parallelization=False): """ if parallelization is True: - logger.info('Parallelization') - + logger.info('Parallelization') raise NotImplementedError -# -# id_list = self._grid_choice['the_selected_network_id'].tolist() -# -# self._pool = run_edisgo_pool_flexible( -# ding0_id_list=id_list, -# func=_run_edisgo, -# func_arguments=[ -# 'args...' -# ]) - + else: no_grids = len(self._grid_choice) count = 0 @@ -239,17 +220,12 @@ def _run_edisgo_pool(self, parallelization=False): edisgo_grid = self._run_edisgo(mv_grid_id) self._edisgo_grids[ mv_grid_id - ] = edisgo_grid -# self._edisgo_costs[ -# mv_grid_id -# ] = costs + ] = edisgo_grid except Exception: self._edisgo_grids[mv_grid_id] = None logger.exception( 'MV grid {} failed: \n'.format(mv_grid_id) - ) - count += 1 def _run_edisgo(self, mv_grid_id): @@ -299,7 +275,6 @@ def _run_edisgo(self, mv_grid_id): edisgo_grid.network.timeseries = TimeSeriesControl( network=edisgo_grid.network, - # Here, I use only normalized values from specs timeseries_generation_fluctuating=specs['potential'], timeseries_generation_dispatchable=specs['conv_dispatch'], timeseries_load='demandlib', @@ -307,8 +282,9 @@ def _run_edisgo(self, mv_grid_id): logger.info('Including Curtailment') gens_df = tools.get_gen_info(edisgo_grid.network) - solar_wind_capacities = gens_df.groupby(by=['type', 'weather_cell_id'])[ - 'nominal_capacity'].sum() + solar_wind_capacities = gens_df.groupby( + by=['type', 'weather_cell_id'] + )['nominal_capacity'].sum() curt_abs = pd.DataFrame(columns=specs['curtailment'].columns) @@ -321,7 +297,6 @@ def _run_edisgo(self, mv_grid_id): logger.warning('Curtailment reduced to 99.9 %') edisgo_grid.curtail(curtailment_methodology='curtail_all', - # Here, I use absolute values timeseries_curtailment=curt_abs) # Think about the other curtailment functions!!!! @@ -330,10 +305,7 @@ def _run_edisgo(self, mv_grid_id): edisgo_grid.reinforce() return edisgo_grid - - - -## Helpful tools + def _get_mv_grid_from_bus_id(self, bus_id): """ Returns the MV grid ID for a given eTraGo bus From 7914cc76bfd006f4055d9f346dd3d4acc630a96c Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 15:59:23 +0200 Subject: [PATCH 261/314] update file --- ego/tools/io.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 7c5f79b2..207e4d80 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -44,11 +44,11 @@ from tools.results import (create_etrago_results) from tools.storages import (total_storage_charges, etrago_storages) from tools.economics import ( - etrago_operating_costs, - etrago_grid_investment, - edisgo_grid_investment, - investment_costs, - get_generator_investment) + etrago_operating_costs, + etrago_grid_investment, + edisgo_grid_investment, + investment_costs, + get_generator_investment) from tools.utilities import get_scenario_setting, get_time_steps from tools.edisgo_integration import EDisGoNetworks from egoio.db_tables.model_draft import RenpassGisParameterRegion @@ -318,9 +318,9 @@ def __init__(self, jsonpath, *args, **kwargs): etrago_network=self.etrago_network) self.edisgo.grid_costs = edisgo_grid_investment( - self.edisgo_networks, - self.json_file - ) + self.edisgo_networks, + self.json_file + ) class eGo(eDisGoResults): @@ -352,14 +352,6 @@ def __init__(self, jsonpath, *args, **kwargs): # add all ego function pass - def __repr__(self): - r = ('eGoResults is created.') - if not self.etrago_network: - r += "\nThe results does not incluede eTraGo results" - if not self.edisgo_network: - r += "\nThe results does not incluede eDisGo results" - return r - # write_results_to_db(): logging.info('Initialisation of eGo Results') From a68210efd7fda4cc9a183e8b8707bc72ac5e78dd Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 17:51:49 +0200 Subject: [PATCH 262/314] update storage_costs --- ego/tools/storages.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 8d5ec9a8..f59ac7e7 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -116,3 +116,33 @@ def etrago_storages(network): storages = total_storage_charges(network=network) return storages + + +def etrago_storages_investment(network): + """Calculate storage investment costs of eTraGo + + Parameters + ---------- + network_etrago: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` + + + Returns + ------- + storage_costs : numeric + Storage costs of selected snapshots in [EUR] + + """ + # provide storage installation costs + if sum(network.storage_units.p_nom_opt) != 0: + installed_storages = \ + network.storage_units[network.storage_units.p_nom_opt != 0] + storage_costs = sum( + installed_storages.capital_cost * + installed_storages.p_nom_opt) + print( + "Investment costs for all storages in selected snapshots [EUR]:", + round( + storage_costs, + 2)) + return storage_costs From 2886f3d12860a4eff3d2cda49c328ce172419d9d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 17:52:07 +0200 Subject: [PATCH 263/314] update storage_investment_costs --- ego/tools/io.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 207e4d80..e1a45828 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -42,7 +42,7 @@ from egoio.db_tables.model_draft import EgoGridPfHvSource as Source,\ EgoGridPfHvTempResolution as TempResolution from tools.results import (create_etrago_results) - from tools.storages import (total_storage_charges, etrago_storages) + from tools.storages import (etrago_storages_investment, etrago_storages) from tools.economics import ( etrago_operating_costs, etrago_grid_investment, @@ -203,14 +203,15 @@ def __init__(self, jsonpath, *args, **kwargs): # add selected results to Results container self.etrago = pd.DataFrame() - self.etrago.storage_charges = total_storage_charges( + self.etrago.storage_investment_costs = etrago_storages_investment( self.etrago_network) - self.etrago.storage_costs = etrago_storages(self.etrago_network) + self.etrago.storage_charges = etrago_storages(self.etrago_network) self.etrago.operating_costs = etrago_operating_costs( self.etrago_network) self.etrago.generator = create_etrago_results(self.etrago_network, self.scn_name) - self.etrago.grid_investment_costs = etrago_grid_investment(self.etrago_network, + self.etrago.grid_investment_costs = etrago_grid_investment(self. + etrago_network, self.json_file) # add functions direct From e42da7cb471fe590d69c52935404c4734761c6f0 Mon Sep 17 00:00:00 2001 From: maltesc Date: Tue, 17 Jul 2018 18:10:23 +0200 Subject: [PATCH 264/314] documentation first version --- ego/ego_main.py | 1 - ego/scenario_setting.json | 2 +- ego/tools/economics.py | 44 ++++++---- ego/tools/edisgo_integration.py | 140 ++++++++++++++++++++------------ ego/tools/io.py | 11 ++- ego/tools/mv_cluster.py | 61 ++++++++++---- ego/tools/specs.py | 127 +++++++---------------------- 7 files changed, 202 insertions(+), 184 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index b03f3dcc..0dab3250 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -52,6 +52,5 @@ logger.info('Print results') ego.etrago_line_loading() print(ego.etrago.generator) - print(ego.etrago.grid_costs) print(ego.etrago.storage_costs) print(ego.etrago.operating_costs) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index f437ba07..587baec0 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -45,7 +45,7 @@ "ding0_files": "data/MV_grids/20180713110719", "choice_mode": "manual", "no_grids": null, - "manual_grids": [1730], + "manual_grids": [1729, 1730], "scn_name": "NEP 2035", "comments": "make a comment" } diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 09e5154a..34d48f7f 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -281,14 +281,19 @@ def etrago_grid_investment(network, json_file): def edisgo_grid_investment(edisgo_networks, json_file): - """Function to get all costs of grid investment of eDisGo. + """ + Function aggregates all costs, based on all calculated eDisGo + grids and their weightings Parameters ---------- - - network_edisgo : :pandas:`pandas.Dataframe` - Network container of eDisGo - + edisgo_networks : :class:`ego.tools.edisgo_integration.EDisGoNetworks` + Contains multiple eDisGo networks + + Returns + ------- + None or :pandas:`pandas.DataFrame` + Dataframe containing annuity costs per voltage level """ @@ -299,9 +304,15 @@ def edisgo_grid_investment(edisgo_networks, json_file): annuity_costs = pd.DataFrame(columns=['v_lev', 'annuity_costs']) for key, value in edisgo_networks.edisgo_grids.items(): + + if value is None: + logger.warning('No results available for grid {}'.format(key)) + continue + costs_single = value.network.results.grid_expansion_costs - if not costs_single: - logger.warning('No results for grid {}'.format(key)) + + if (costs_single['total_costs'].sum() == 0.): + logger.info('No expansion costs for grid {}'.format(key)) continue costs_single = costs_single.rename( @@ -327,14 +338,19 @@ def edisgo_grid_investment(edisgo_networks, json_file): costs_single = costs_single[['v_lev', 'annuity_costs']] annuity_costs = annuity_costs.append(costs_single, ignore_index=True) - - aggr_capital_costs = annuity_costs.groupby(['v_lev']).sum().reset_index() - aggr_capital_costs = aggr_capital_costs.rename( - columns={'annuity_costs': 'grid_costs'} - ) - aggr_capital_costs['grid_costs'] = aggr_capital_costs['grid_costs'] * 1000 + + if len(annuity_costs) == 0: + logger.info('No expansion costs in any MV grid') + return None - return aggr_capital_costs + else: + aggr_capital_costs = annuity_costs.groupby(['v_lev']).sum().reset_index() + aggr_capital_costs = aggr_capital_costs.rename( + columns={'annuity_costs': 'grid_costs'} + ) + aggr_capital_costs['grid_costs'] = aggr_capital_costs['grid_costs'] * 1000 + + return aggr_capital_costs def get_generator_investment(network, scn_name): diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index a3143ca0..ef323899 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -86,7 +86,7 @@ def __init__(self, json_file, etrago_network): self._generator_scn = None elif self._scn_name == 'NEP 2035': self._generator_scn = 'nep2035' - elif self._scn_name == 'eGo100': + elif self._scn_name == 'eGo 100': self._generator_scn = 'ego100' if self._grid_version is not None: @@ -107,12 +107,12 @@ def __init__(self, json_file, etrago_network): @property def edisgo_grids(self): """ - Container of + Container for eDisGo grids, including all results Returns ------- - :obj:`collections.OrderedDict` - Configuration data from config files. + :obj:`dict` of :class:`edisgo.grid.network.EDisGo` + Dictionary of eDisGo objects, keyed by MV grid ID """ return self._edisgo_grids @@ -120,8 +120,13 @@ def edisgo_grids(self): @property def grid_choice(self): """ - Returns the chosen grids - + Container for the choice of MV grids, including their weighting + + Returns + ------- + :pandas:`pandas.DataFrame` + Dataframe containing the chosen grids and their weightings + """ return self._grid_choice @@ -134,7 +139,18 @@ def _analyze_cluster_attributes(self): def _cluster_mv_grids(self, no_grids): """ - Clusters the MV grids based on the attributes + Clusters the MV grids based on the attributes, for a given number + of MV grids + + Parameters + ---------- + no_grids : int + Desired number of clusters (of MV grids) + + Returns + ------- + :pandas:`pandas.DataFrame` + Dataframe containing the clustered MV grids and their weightings """ attributes_path = self._ding0_files + '/attributes.csv' @@ -148,7 +164,12 @@ def _cluster_mv_grids(self, no_grids): def _check_available_mv_grids(self): """ - Checks all available MV grids in the given folder from the settings + Checks all available MV grids in the given folder (from the settings) + + Returns + ------- + :obj:`list` + List of MV grid ID's """ mv_grids = [] @@ -194,45 +215,50 @@ def _set_grid_choice(self): self._grid_choice = cluster - def _run_edisgo_pool(self, parallelization=False): + def _run_edisgo_pool(self): """ Runs eDisGo for the chosen grids """ - if parallelization is True: - logger.info('Parallelization') - raise NotImplementedError - - else: - no_grids = len(self._grid_choice) - count = 0 - for idx, row in self._grid_choice.iterrows(): - prog = '%.1f' % (count / no_grids * 100) - logger.info( - '{} % Calculated by eDisGo'.format(prog) - ) + logger.warning('Parallelization not implemented yet') + no_grids = len(self._grid_choice) + count = 0 + for idx, row in self._grid_choice.iterrows(): + prog = '%.1f' % (count / no_grids * 100) + logger.info( + '{} % Calculated by eDisGo'.format(prog) + ) - mv_grid_id = int(row['the_selected_network_id']) - logger.info( - 'MV grid {}'.format(mv_grid_id) + mv_grid_id = int(row['the_selected_network_id']) + logger.info( + 'MV grid {}'.format(mv_grid_id) + ) + try: + edisgo_grid = self._run_edisgo(mv_grid_id) + self._edisgo_grids[ + mv_grid_id + ] = edisgo_grid + except Exception: + self._edisgo_grids[mv_grid_id] = None + logger.exception( + 'MV grid {} failed: \n'.format(mv_grid_id) ) - try: - edisgo_grid = self._run_edisgo(mv_grid_id) - self._edisgo_grids[ - mv_grid_id - ] = edisgo_grid - except Exception: - self._edisgo_grids[mv_grid_id] = None - logger.exception( - 'MV grid {} failed: \n'.format(mv_grid_id) - ) - count += 1 + count += 1 def _run_edisgo(self, mv_grid_id): """ - Runs eDisGo with the desired settings. + Performs a single eDisGo run + Parameters + ---------- + mv_grid_id : int + MV grid ID of the ding0 grid + + Returns + ------- + :class:`edisgo.grid.network.EDisGo` + Returns the complete eDisGo container, also including results """ logger.info('Calculating interface values') @@ -260,8 +286,7 @@ def _run_edisgo(self, mv_grid_id): ding0_filepath=ding0_filepath, generator_scenario=None, analysis='worst-case')[0] # only the edisgo_grid is returned - - + logger.info('eTraGo feed-in case') edisgo_grid.network.results = Results() @@ -272,7 +297,8 @@ def _run_edisgo(self, mv_grid_id): ) edisgo_grid.import_generators( generator_scenario=self._generator_scn) - + + logger.info('Updating eDisGo timeseries with eTraGo values') edisgo_grid.network.timeseries = TimeSeriesControl( network=edisgo_grid.network, timeseries_generation_fluctuating=specs['potential'], @@ -293,9 +319,6 @@ def _run_edisgo(self, mv_grid_id): specs['curtailment'][col] * solar_wind_capacities[col]) - curt_abs = curt_abs * 0.999 - logger.warning('Curtailment reduced to 99.9 %') - edisgo_grid.curtail(curtailment_methodology='curtail_all', timeseries_curtailment=curt_abs) # Think about the other curtailment functions!!!! @@ -308,8 +331,18 @@ def _run_edisgo(self, mv_grid_id): def _get_mv_grid_from_bus_id(self, bus_id): """ - Returns the MV grid ID for a given eTraGo bus - + Queries the MV grid ID for a given eTraGo bus + + Parameters + ---------- + bus_id : int + eTraGo bus ID + + Returns + ------- + int + MV grid (ding0) ID + """ if self._versioned is True: @@ -337,8 +370,18 @@ def _get_mv_grid_from_bus_id(self, bus_id): def _get_bus_id_from_mv_grid(self, subst_id): """ - Returns the eTraGo bus ID for a given MV grid - + Queries the eTraGo bus ID for given MV grid (ding0) ID + + Parameters + ---------- + subst_id : int + MV grid (ding0) ID + + Returns + ------- + int + eTraGo bus ID + """ if self._versioned is True: ormclass_hvmv_subst = grid.__getattribute__( @@ -361,7 +404,4 @@ def _get_bus_id_from_mv_grid(self, subst_id): ormclass_hvmv_subst.subst_id == subst_id ).scalar() - return bus_id - - def _get_hvmv_translation(self): - raise NotImplementedError \ No newline at end of file + return bus_id \ No newline at end of file diff --git a/ego/tools/io.py b/ego/tools/io.py index 7c5f79b2..1faad9c0 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -297,9 +297,9 @@ def etrago_full_load_hours(self, **kwargs): class eDisGoResults(eTraGoResults): - """ eDisGo Results + """The ``eDisGoResults`` class create and contains all results + of eDisGo and its network containers. - This module contains all results of eDisGo for eGo. """ def __init__(self, jsonpath, *args, **kwargs): @@ -317,12 +317,11 @@ def __init__(self, jsonpath, *args, **kwargs): json_file=self.json_file, etrago_network=self.etrago_network) - self.edisgo.grid_costs = edisgo_grid_investment( + self.edisgo.grid_investment_costs = edisgo_grid_investment( self.edisgo_networks, self.json_file ) - class eGo(eDisGoResults): """Main eGo module which including all results and main functionalities. @@ -331,8 +330,8 @@ class eGo(eDisGoResults): ------- network_etrago: :class:`etrago.tools.io.NetworkScenario` eTraGo network object compiled by :meth:`etrago.appl.etrago` - network_edisgo : :pandas:`pandas.Dataframe` - Network container of eDisGo + edisgo_networks : :class:`ego.tools.edisgo_integration.EDisGoNetworks` + Contains multiple eDisGo networks edisgo : :pandas:`pandas.Dataframe` aggregated results of eDisGo etrago : :pandas:`pandas.Dataframe` diff --git a/ego/tools/mv_cluster.py b/ego/tools/mv_cluster.py index 9cb39644..0eca5734 100644 --- a/ego/tools/mv_cluster.py +++ b/ego/tools/mv_cluster.py @@ -18,24 +18,41 @@ # File description """ -Make MV Cluster +This file contains all functions regarding the clustering of MV grids """ - -from __future__ import print_function - -import pickle +__copyright__ = ("Flensburg University of Applied Sciences, " + "Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke, maltesc" + +# Import +#from __future__ import print_function import os -import pandas as pd - -from sklearn.cluster import KMeans -import numpy as np -import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d import Axes3D -import matplotlib.cm as cm +if not 'READTHEDOCS' in os.environ: + import pickle + + import pandas as pd + + from sklearn.cluster import KMeans + import numpy as np + + #import matplotlib.pyplot as plt + #from mpl_toolkits.mplot3d import Axes3D + #import matplotlib.cm as cm def analyze_attributes(ding0_files): - + """ + Calculates the attributes wind and solar capacity and farthest node + for all files in ding0_files. Results are written to ding0_files + + Parameters + ---------- + ding0_files : :obj:`str` + Path to ding0 files + + """ base_path = ding0_files not_found = [] @@ -195,7 +212,23 @@ def analyze_attributes(ding0_files): def cluster_mv_grids(ding0_files, no_grids): - + """ + Clusters the MV grids based on the attributes, for a given number + of MV grids + + Parameters + ---------- + ding0_files : :obj:`str` + Path to ding0 files + no_grids : int + Desired number of clusters (of MV grids) + + Returns + ------- + :pandas:`pandas.DataFrame` + Dataframe containing the clustered MV grids and their weightings + + """ # import CSV data file that exported from Networks_analysis_solar_wind_farthest-node.py and assign it to a data frame df = pd.read_csv(ding0_files + '/attributes.csv') diff --git a/ego/tools/specs.py b/ego/tools/specs.py index d3f47bfa..04afd939 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -18,14 +18,21 @@ # File description """ +This files contains all eGo interface functions """ + +__copyright__ = ("Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") +__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" +__author__ = "wolf_bunke,maltesc" + # Import # General Packages import os import pandas as pd import time if not 'READTHEDOCS' in os.environ: - from sqlalchemy import distinct +# from sqlalchemy import distinct # This gives me the specific ORM classes. from egoio.db_tables import model_draft # from edisgo.grid.network import ETraGoSpecs @@ -33,11 +40,6 @@ import logging logger = logging.getLogger('ego') -__copyright__ = ("Europa-Universität Flensburg, " - "Centre for Sustainable Energy Systems") -__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolf_bunke,maltesc" - # Functions @@ -392,21 +394,25 @@ def get_etragospecs_direct(session, etrago_network, scn_name): """ - Reads eTraGo Results from Database and returns an Object of the Interface class ETraGoSpecs - + Reads eTraGo Results from Database and returns and returns + the interface values as a dictionary of corresponding dataframes + Parameters ---------- - session : :class:`~.` #Todo: Add class etc.... - Oemof session object (Database Interface) + session : sqla.orm.session.Session + Handles conversations with the database. bus_id : int ID of the corresponding HV bus - eTraGo : :class:`~.` #Todo: Add class etc.... + etrago_network: :class:`etrago.tools.io.NetworkScenario` + eTraGo network object compiled by :meth:`etrago.appl.etrago` + scn_name : str + Name of used scenario 'Status Quo', 'NEP 2035' or 'eGo 100' Returns ------- - etragospecs : :class:~.` - eDisGo ETraGoSpecs Object + :obj:`dict` of :pandas:`pandas.DataFrame` + Dataframes used as eDisGo inputs """ @@ -555,15 +561,15 @@ def get_etragospecs_direct(session, index=snap_idx, columns=aggr_gens['ren_id']) - potential_abs = pd.DataFrame(0.0, - index=snap_idx, - columns=aggr_gens['ren_id']) - dispatch_abs = pd.DataFrame(0.0, - index=snap_idx, - columns=aggr_gens['ren_id']) - curtailment_abs = pd.DataFrame(0.0, - index=snap_idx, - columns=aggr_gens['ren_id']) +# potential_abs = pd.DataFrame(0.0, +# index=snap_idx, +# columns=aggr_gens['ren_id']) +# dispatch_abs = pd.DataFrame(0.0, +# index=snap_idx, +# columns=aggr_gens['ren_id']) +# curtailment_abs = pd.DataFrame(0.0, +# index=snap_idx, +# columns=aggr_gens['ren_id']) for index, row in ren_df.iterrows(): gen_id = row['generator_id'] @@ -739,79 +745,4 @@ def get_etragospecs_direct(session, # for keys,values in performance.items(): # print(keys, ": ", values) - return specs - - -#def get_mvgrid_from_bus_id(session, -# bus_id): -# # Mapping -# ormclass_hvmv_subst = model_draft.__getattribute__('EgoGridHvmvSubstation') -# subst_id = session.query( -# ormclass_hvmv_subst.subst_id -# ).filter( -# ormclass_hvmv_subst.otg_id == bus_id -# ).scalar( -# ) -# # ToDo Check if subst_id is really the mv grid ID -# # Anyway, this should be adapted by Dingo -# return subst_id - -#def get_feedin_fluctuating(ren_dispatch, curtailment, renewables): -# -# # get feed-in without curtailment -# if curtailment is not None: -# print(ren_dispatch) -# print(curtailment) -# feedin = ren_dispatch + curtailment -# print(feedin) -# logger.info('Feed-in calculated including curtailment') -# else: -# feedin = ren_dispatch -# # change column names -# new_columns = [ -# (renewables[renewables.ren_id == col].name.iloc[0], -# renewables[renewables.ren_id == col].w_id.iloc[0]) -# for col in feedin.columns] -# feedin.columns = pd.MultiIndex.from_tuples(new_columns) -# # aggregate wind and solar time series until generators get a weather -# # ID -# print(feedin) -# return feedin - - -#def get_curtailment(edisgo_grid, curtailment, renewables): -# -# # get installed capacities of wind and solar generators -# # ToDo: Differentiate by weather cell ID once generators have one -# gens = list(edisgo_grid.network.mv_grid.graph.nodes_by_attribute( -# 'generator')) -# for lv_grid in edisgo_grid.network.mv_grid.lv_grids: -# gens.extend(list(lv_grid.graph.nodes_by_attribute('generator'))) -# dict_capacities = {'solar': 0, 'wind': 0} -# for gen in gens: -# if gen.type in ['solar', 'wind']: -# dict_capacities[gen.type] = ( -# dict_capacities[gen.type] -# + gen.nominal_capacity) -# print(dict_capacities) -# -# # change column names of curtailment DataFrame to -# new_columns = [ -# (renewables[renewables.ren_id == col].name.iloc[0], -# renewables[renewables.ren_id == col].w_id.iloc[0]) -# for col in curtailment.columns] -# curtailment.columns = pd.MultiIndex.from_tuples(new_columns) -# -# -# return curtailment - -#Hier curtailment noch zusammenfassen!! - -# curtailment = pd.DataFrame(data={'wind': curtailment.wind.sum(axis=1), -# 'solar': curtailment.solar.sum(axis=1)}) -# -# # calculate absolute curtailment -# timeseries_curtailment = curtailment.multiply( -# pd.Series(dict_capacities)) -# -# return timeseries_curtailment \ No newline at end of file + return specs \ No newline at end of file From dbfb8eb24e08afd69708802e71697afde836e25d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 18:49:55 +0200 Subject: [PATCH 265/314] remove merge message --- ego/tools/io.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index bc72d0f9..17df6243 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -318,17 +318,11 @@ def __init__(self, jsonpath, *args, **kwargs): json_file=self.json_file, etrago_network=self.etrago_network) -<<<<<<< HEAD self.edisgo.grid_costs = edisgo_grid_investment( self.edisgo_networks, self.json_file ) -======= - self.edisgo.grid_investment_costs = edisgo_grid_investment( - self.edisgo_networks, - self.json_file - ) ->>>>>>> bfb1615171dd00c37c1510050bd6c92490d27343 + class eGo(eDisGoResults): """Main eGo module which including all results and main functionalities. From 4bdcf6efaf70cb4407e79c3551193bbfec907e96 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 19:25:25 +0200 Subject: [PATCH 266/314] update docu --- doc/api/modules.rst | 2 +- doc/conf.py | 3 ++- doc/installation.rst | 2 +- ego/ego_main.py | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index 42b02230..e568c668 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -11,8 +11,8 @@ Overview of modules .. toctree:: :maxdepth: 4 - ego.ego_main ego.tools + ego ego_main.py diff --git a/doc/conf.py b/doc/conf.py index 9092938d..9c5697ca 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -36,6 +36,7 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, os.path.abspath('../')) +sys.path.insert(0, os.path.abspath('../..')) # -- General configuration ------------------------------------------------ @@ -176,7 +177,7 @@ def setup(app): # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build', 'whatsnew'] +exclude_patterns = ['_build', 'whatsnew', '_static'] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/doc/installation.rst b/doc/installation.rst index 48717561..6be71a9f 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -62,7 +62,7 @@ environments. Setup database connection ========================= The package ``ego.io`` gives you a python SQL-Alchemy representations of -the _OpenEnergy-Database_ (oedb) and access to it by using the +the **OpenEnergy-Database** (oedb) and access to it by using the `oedialect `_ a SQL-Alchemy binding Python package for the REST-API used by the OpenEnergy Platform (OEP). Your API access / login data will be saved in the folder ``.egoio`` in the file diff --git a/ego/ego_main.py b/ego/ego_main.py index 0dab3250..bb3c6f57 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -32,8 +32,8 @@ if not 'READTHEDOCS' in os.environ: - from ego.tools.io import eGo - from ego.tools.utilities import define_logging + from tools.io import eGo + from tools.utilities import define_logging logger = define_logging(log_name='ego.log') __copyright__ = ("Flensburg University of Applied Sciences, " From 5be1a6268807b991779a305ceb767099956fd3f1 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Tue, 17 Jul 2018 19:56:22 +0200 Subject: [PATCH 267/314] fix RTD autodoc --- doc/api/ego.rst | 29 ----------------------------- doc/api/modules.rst | 4 ++-- doc/conf.py | 2 ++ ego/tools/economics.py | 2 +- ego/tools/io.py | 10 +++++----- ego/tools/plots.py | 2 +- ego/tools/results.py | 2 +- ego/tools/storages.py | 9 +++++---- 8 files changed, 17 insertions(+), 43 deletions(-) delete mode 100644 doc/api/ego.rst diff --git a/doc/api/ego.rst b/doc/api/ego.rst deleted file mode 100644 index 23ab3555..00000000 --- a/doc/api/ego.rst +++ /dev/null @@ -1,29 +0,0 @@ -ego package -=========== - -Subpackages ------------ - -.. toctree:: - - ego.tools - -Submodules ----------- - -ego\.ego_main -------------- - -.. automodule:: ego.ego_main - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: ego - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/api/modules.rst b/doc/api/modules.rst index e568c668..08a71541 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -9,10 +9,10 @@ Overview of modules .. toctree:: - :maxdepth: 4 + :maxdepth: 7 ego.tools - ego + ego_main.py diff --git a/doc/conf.py b/doc/conf.py index 9c5697ca..651d9672 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -64,6 +64,8 @@ ] +# https://stackoverflow.com/questions/12206334/sphinx-autosummary-toctree-contains-reference-to-nonexisting-document-warnings +numpydoc_show_class_members = False # Napoleon settings napoleon_google_docstring = True diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 34d48f7f..0dc0ebfa 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -29,7 +29,7 @@ if not 'READTHEDOCS' in os.environ: import pandas as pd import numpy as np - from tools.utilities import get_time_steps + from ego.tools.utilities import get_time_steps __copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ "Flensburg, Centre for Sustainable Energy Systems" diff --git a/ego/tools/io.py b/ego/tools/io.py index 17df6243..2b915aa4 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -41,16 +41,16 @@ from etrago.tools.io import load_config_file from egoio.db_tables.model_draft import EgoGridPfHvSource as Source,\ EgoGridPfHvTempResolution as TempResolution - from tools.results import (create_etrago_results) - from tools.storages import (etrago_storages_investment, etrago_storages) - from tools.economics import ( + from ego.tools.results import (create_etrago_results) + from ego.tools.storages import (etrago_storages_investment, etrago_storages) + from ego.tools.economics import ( etrago_operating_costs, etrago_grid_investment, edisgo_grid_investment, investment_costs, get_generator_investment) - from tools.utilities import get_scenario_setting, get_time_steps - from tools.edisgo_integration import EDisGoNetworks + from ego.tools.utilities import get_scenario_setting, get_time_steps + from ego.tools.edisgo_integration import EDisGoNetworks from egoio.db_tables.model_draft import RenpassGisParameterRegion from egoio.db_tables import model_draft, grid from etrago.tools.plot import (plot_line_loading, plot_stacked_gen, diff --git a/ego/tools/plots.py b/ego/tools/plots.py index 8bed1278..26db9454 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -40,7 +40,7 @@ import webbrowser from egoio.db_tables.model_draft import EgoGridMvGriddistrict from egoio.db_tables.grid import EgoDpMvGriddistrict - from tools.io import eGo + from ego.tools.io import eGo import matplotlib.pyplot as plt import logging diff --git a/ego/tools/results.py b/ego/tools/results.py index e5b083db..57d26a70 100644 --- a/ego/tools/results.py +++ b/ego/tools/results.py @@ -30,7 +30,7 @@ if not 'READTHEDOCS' in os.environ: import pandas as pd import numpy as np - from tools.economics import get_generator_investment + from ego.tools.economics import get_generator_investment __copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ "Flensburg, Centre for Sustainable Energy Systems" diff --git a/ego/tools/storages.py b/ego/tools/storages.py index f59ac7e7..071e94ca 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -41,7 +41,7 @@ def total_storage_charges(network): Parameters ---------- - network : :etrago:`etrago.tools.io.NetworkScenario` + network : :class:`etrago.tools.io.NetworkScenario` eTraGo ``NetworkScenario`` based on PyPSA Network. See also `pypsa.network `_ @@ -102,7 +102,7 @@ def etrago_storages(network): Parameters ---------- - network : :class:`~.etrago.tools.io.NetworkScenario` + network : :class:`etrago.tools.io.NetworkScenario` eTraGo ``NetworkScenario`` based on PyPSA Network. See also `pypsa.network `_ @@ -123,8 +123,9 @@ def etrago_storages_investment(network): Parameters ---------- - network_etrago: :class:`etrago.tools.io.NetworkScenario` - eTraGo network object compiled by :meth:`etrago.appl.etrago` + network : :class:`etrago.tools.io.NetworkScenario` + eTraGo ``NetworkScenario`` based on PyPSA Network. See also + `pypsa.network `_ Returns From 5ba58ec47b964514371094e472e9862cd40f82db Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 08:37:51 +0200 Subject: [PATCH 268/314] update RTD docu --- ego/tools/io.py | 29 +++-------------------------- ego/tools/storages.py | 1 + 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 2b915aa4..8719d8e5 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -72,21 +72,16 @@ class egoBasic(object): """The eGo basic class select and creates based on your ``scenario_setting.json`` file your definde eTraGo and - eDisGo results container. - + eDisGo results container. And contains the session for the + database connection. Parameters ---------- jsonpath : :obj:`json` Path to ``scenario_setting.json`` file. - Returns ------- - network_etrago: :class:`etrago.tools.io.NetworkScenario` - eTraGo network object compiled by :meth:`etrago.appl.etrago` - network_edisgo : :pandas:`pandas.Dataframe` - Network container of eDisGo json_file : :obj:dict Dictionary of the ``scenario_setting.json`` file session : :sqlalchemy:`sqlalchemy.orm.session.Session` @@ -126,25 +121,7 @@ class eTraGoResults(egoBasic): network_etrago: :class:`etrago.tools.io.NetworkScenario` eTraGo network object compiled by :meth:`etrago.appl.etrago` etrago: :pandas:`pandas.Dataframe` - eTraGo results - - Examples - -------- - - The module can be used by ``network = eTraGoResults()`` - - See also - -------- - - The `eTraGo`_ documentation. - - - - References - ---------- - .. _eTraGo: - `eTraGo `_, \ - eTraGo Documentation. + DataFrame which collects several eTraGo results """ def __init__(self, jsonpath, *args, **kwargs): diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 071e94ca..80b289f3 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -138,6 +138,7 @@ def etrago_storages_investment(network): if sum(network.storage_units.p_nom_opt) != 0: installed_storages = \ network.storage_units[network.storage_units.p_nom_opt != 0] + storage_costs = pd.DataFrame() storage_costs = sum( installed_storages.capital_cost * installed_storages.p_nom_opt) From 403b146d69ca2df0b01b9a946b4e5d15eafe2fb4 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 09:10:19 +0200 Subject: [PATCH 269/314] update logger --- ego/tools/utilities.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index b6342d80..c587389a 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -39,36 +39,31 @@ def define_logging(log_name='ego.log'): log_name : str Name of log file. Default: ``ego.log``. - Returns ------- - ego_logger : :class:`logging.basicConfig`. - Set up ``ego_logger`` object of package ``logging`` + logger : :class:`logging.basicConfig`. + Set up ``logger`` object of package ``logging`` """ # ToDo: Logger should be set up more specific # add pypsa and other logger INFO to ego.log - logging.basicConfig(level=logging.INFO) - logger = logging.getLogger(__name__) - # Logging logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) - ego_logger = logging.getLogger('ego') + logger = logging.getLogger('ego') + + logger = logging.FileHandler(log_name, mode='w') - fh = logging.FileHandler(log_name, mode='w') - fh.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(name)s - \ %(levelname)s - %(message)s') - fh.setFormatter(formatter) + logger.setFormatter(formatter) - logger.addHandler(fh) - ego_logger.addHandler(fh) + # logger.addHandler(xy) - return ego_logger + return logger logger = define_logging(log_name='ego.log') From 4a0b5703c871b4dfb6f5aaed2947884ca4bdbf81 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 09:10:35 +0200 Subject: [PATCH 270/314] update documentation --- ego/tools/io.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 8719d8e5..120b9f81 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -326,8 +326,9 @@ def __init__(self, jsonpath, *args, **kwargs): # super().__init__(eDisGo) self.total = pd.DataFrame() # add total results here + self.total_investment_costs = investment_costs(self.etrago_network) + self.total_operation_costs = pd.DataFrame() # TODO - # add all ego function pass # write_results_to_db(): From e657df3784489e072b6b272a496450b2f96a4d90 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 09:10:51 +0200 Subject: [PATCH 271/314] update documentation --- ego/tools/economics.py | 107 ++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 0dc0ebfa..73fee6cf 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -100,7 +100,6 @@ def edisgo_convert_capital_costs(overnight_cost, t, p, json_file): # Based on eTraGo calculation in # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 - # Calculate present value of an annuity (PVA) PVA = (1 / p) - (1 / (p*(1 + p) ** t)) @@ -126,20 +125,37 @@ def etrago_operating_costs(network): Returns ------- power_price : :pandas:`pandas.Dataframe` + DataFrame with aggregate operational costs per component and voltage + level in [EUR] per calculated time steps. - Examples - -------- + Example + ------- + + .. code-block:: python + + >>> from ego.tools.io import eGo + >>> ego = eGo(jsonpath='scenario_setting.json') + >>> ego.etrago.operating_costs - - losses - - grid losses : amount and costs - - use calc_line_losses(network) from etrago pf_post_lopf + +-------------+-------------------+------------+ + | component |operation_costs | v_level | + +=============+===================+============+ + |biomass | 27.0 | | + +-------------+-------------------+------------+ + |line losses | 0.0 | | + +-------------+-------------------+------------+ + |wind_onshore | 0.0 | | + +-------------+-------------------+------------+ """ # TODO - change naming and function structure # TODO - seperate operation costs in other functions ? + # - losses + # - grid losses : amount and costs + # - use calc_line_losses(network) from etrago pf_post_lopf etg = network - # etg = eTraGo + # groupby v_nom power_price = etg.generators_t.p[etg.generators[etg.generators. control != 'Slack'].index] * etg.generators.\ @@ -279,7 +295,6 @@ def etrago_grid_investment(network, json_file): pass - def edisgo_grid_investment(edisgo_networks, json_file): """ Function aggregates all costs, based on all calculated eDisGo @@ -289,7 +304,7 @@ def edisgo_grid_investment(edisgo_networks, json_file): ---------- edisgo_networks : :class:`ego.tools.edisgo_integration.EDisGoNetworks` Contains multiple eDisGo networks - + Returns ------- None or :pandas:`pandas.DataFrame` @@ -299,67 +314,69 @@ def edisgo_grid_investment(edisgo_networks, json_file): t = 40 p = 0.05 - logger.warning('For all components T={} and p={} is used'.format(t, p)) - + logger.warning('For all components T={} and p={} is used'.format(t, p)) + annuity_costs = pd.DataFrame(columns=['v_lev', 'annuity_costs']) - + for key, value in edisgo_networks.edisgo_grids.items(): - + if value is None: logger.warning('No results available for grid {}'.format(key)) continue - + costs_single = value.network.results.grid_expansion_costs - + if (costs_single['total_costs'].sum() == 0.): logger.info('No expansion costs for grid {}'.format(key)) continue costs_single = costs_single.rename( - columns={'voltage_level': 'v_lev'} - ) - + columns={'voltage_level': 'v_lev'} + ) + choice = edisgo_networks.grid_choice weighting = choice.loc[ - choice['the_selected_network_id'] == key - ][ - 'no_of_points_per_cluster' - ].values[0] - + choice['the_selected_network_id'] == key + ][ + 'no_of_points_per_cluster' + ].values[0] + costs_single['annuity_costs'] = edisgo_convert_capital_costs( - costs_single['total_costs'], - t=t, - p=p, - json_file=json_file) - + costs_single['total_costs'], + t=t, + p=p, + json_file=json_file) + costs_single['annuity_costs'] = ( - costs_single['annuity_costs'] * weighting) - + costs_single['annuity_costs'] * weighting) + costs_single = costs_single[['v_lev', 'annuity_costs']] - + annuity_costs = annuity_costs.append(costs_single, ignore_index=True) - + if len(annuity_costs) == 0: logger.info('No expansion costs in any MV grid') return None - + else: - aggr_capital_costs = annuity_costs.groupby(['v_lev']).sum().reset_index() + aggr_capital_costs = annuity_costs.groupby( + ['v_lev']).sum().reset_index() aggr_capital_costs = aggr_capital_costs.rename( - columns={'annuity_costs': 'grid_costs'} - ) + columns={'annuity_costs': 'grid_costs'} + ) aggr_capital_costs['grid_costs'] = aggr_capital_costs['grid_costs'] * 1000 - + return aggr_capital_costs def get_generator_investment(network, scn_name): - """ Get investment costs per carrier/gernator. + """ Get investment costs per carrier/ generator. + - work around later db table -> check capital_cost as cost input?!? """ # TODO - change values in csv # - add values to database + # work around later db table -> check capital_cost as cost input?!? etg = network @@ -391,16 +408,16 @@ def get_generator_investment(network, scn_name): def investment_costs(network): """Return pandas DataFrame with investment costs of - etrago: - Storages - Line extentation - edisgo: - Line extentation - Storage costs? """ # TODO add edisgo + # etrago: + # Storages + # Line extentation + # edisgo: + # Line extentation + # Storage costs? etg = network invest = pd.DataFrame() From 29e0f1be18fc040b48bec233851264023c934c95 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 09:17:29 +0200 Subject: [PATCH 272/314] update file --- ego/tools/io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 120b9f81..f04a0c20 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -326,7 +326,7 @@ def __init__(self, jsonpath, *args, **kwargs): # super().__init__(eDisGo) self.total = pd.DataFrame() # add total results here - self.total_investment_costs = investment_costs(self.etrago_network) + self.total_investment_costs = pd.DataFrame() # TODO self.total_operation_costs = pd.DataFrame() # TODO pass From 9409b04b5842b354b58d4298764db19b66fb2f22 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 09:17:42 +0200 Subject: [PATCH 273/314] update file --- ego/tools/economics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 73fee6cf..39eaf332 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -411,6 +411,7 @@ def investment_costs(network): """ + # TODO Function outdated? # TODO add edisgo # etrago: # Storages From 4b60d82c76cff51a7fd7f09cbf90c801a3b7f200 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 09:18:47 +0200 Subject: [PATCH 274/314] update file --- ego/tools/economics.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 39eaf332..1f077620 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -60,12 +60,6 @@ def annuity_per_period(capex, n, wacc, t, p): return capex * (wacc * (1 + wacc) ** n) / ((1 + wacc) ** n - 1) -# grid_components = {"hv_mv_transformer": "40 MVA", "mv_lv_transformer": "630 kVA", -# "mv_line": "NA2XS2Y 3x1x185 RM/25", "lv_line": "NAYY 4x1x150"} -# json_file = ego.json_file -# cost_config = {"p": 0.04} - - def edisgo_convert_capital_costs(overnight_cost, t, p, json_file): """ Get scenario and calculation specific annuity cost by given capital costs and lifetime. From 4bde46fba380f25cb4719b9d09df53d3b2eb66cb Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 09:22:15 +0200 Subject: [PATCH 275/314] update docu --- doc/api/modules.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index 08a71541..801fd684 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -18,6 +18,13 @@ Overview of modules ego_main.py =========== +This is the application file for the tool eGo. The application eGo calculates +the distribution and transmission grids of eTraGo and eDisGo. + +.. note:: Note, the data source of eGo relies on + the Open Energy Database. - The registration for the public + accessible API can be found on + `openenergy-platform.org/login `_. Run the ``ego_main.py`` file with: From 232ac9f366ec9f05b79c8203cfc774424e2070e0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 09:33:16 +0200 Subject: [PATCH 276/314] update version no :sparkles: --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9412e04a..15976bcd 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ def read(fname): setup(name='eGo', - version='0.2dev', + version='0.2', author='wolfbunke, maltesc', author_email='', description=("A python package for distribution and transmission" From 80316565eca83593eb9069bd40e0b5cc4e600405 Mon Sep 17 00:00:00 2001 From: maltesc Date: Wed, 18 Jul 2018 09:46:32 +0200 Subject: [PATCH 277/314] Testing documentation :star: :frog: --- ego/tools/edisgo_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index ef323899..024a04b2 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -107,7 +107,7 @@ def __init__(self, json_file, etrago_network): @property def edisgo_grids(self): """ - Container for eDisGo grids, including all results + Container for eDisGo grids, including all results :star: Returns ------- From f39f3c4a84c935f7d609075978d8d6e951e06840 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 12:06:08 +0200 Subject: [PATCH 278/314] add and start with json docu --- doc/api/modules.rst | 49 +++++++++++++++++++++++++++++++++++++++++ doc/conf.py | 7 +++--- doc/developer.rst | 1 + doc/getting_started.rst | 3 +++ setup.py | 2 +- 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index 801fd684..24df97f9 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -13,6 +13,55 @@ Overview of modules ego.tools +scenario_settings.json +====================== + +https://sphinx-jsondomain.readthedocs.io/en/latest/examples.html#github-user +https://etrago.readthedocs.io/en/latest/api/etrago.html#module-etrago.appl + +.. json:object:: scenario_setting.json + + Text Text scenario_setting.json + + + + :property global: Global settings + :proptype global: :json:object:`global setting` + :property eTraGo: eDisGo settings + :proptype eTraGo: :json:object:`eTraGo settings` + :property eDisGo: eDisGo settings + :proptype eDisGo: :json:object:`eDisGo settings` + + +.. json:object:: global settings + + Text Text + + + :property bool eTraGo: ``true`` or ``false`` + :property bool eDisGo: ``true`` or ``false``... + :property string db: Name od db, default="oedb" + + +.. json:object:: eTraGo settings + + Text Text + + + :property bool pf_post_lopf: ``true`` or ``false`` + :property string method: "lopf + :property int start_snapshot: Start hour of calcualtion + + + +.. json:object:: eDisGo settings + + Text Text + + + :property pf_post_lopf: ``true`` or ``false`` + :property method: "lopf + :property int start_snapshot: Start hour of calcualtion ego_main.py diff --git a/doc/conf.py b/doc/conf.py index 651d9672..ebac9384 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -60,7 +60,8 @@ 'numpydoc', 'sphinxcontrib.httpdomain', # for restfull API 'sphinxcontrib.autohttp.flask', - 'sphinx.ext.extlinks' # enables external links with a key + 'sphinx.ext.extlinks', # enables external links with a key + 'sphinxjsondomain' ] @@ -117,12 +118,12 @@ def setup(app): import json path = os.getcwd() -json_file ='../ego/scenario_setting.json' +json_file = '../ego/scenario_setting.json' with open(path +'/'+json_file) as f: scn_set = json.load(f) - +json_global = list(scn_set['eTraGo']) html_context = { 'power_class': power_class, diff --git a/doc/developer.rst b/doc/developer.rst index 39e135e0..43c0e72f 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -88,3 +88,4 @@ Change of units from Mega to kilo: eTraGo ====== + diff --git a/doc/getting_started.rst b/doc/getting_started.rst index 45eb747a..b2154e61 100644 --- a/doc/getting_started.rst +++ b/doc/getting_started.rst @@ -10,6 +10,9 @@ How to use eGo? 2. Start your calculation with predefined results tools and run under ``eGo/ego`` the main file with ``>>> python3 ego_main.py`` + + + .. code-block:: bash diff --git a/setup.py b/setup.py index 15976bcd..b8d5f597 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ def read(fname): setup(name='eGo', - version='0.2', + version='0.2.0', author='wolfbunke, maltesc', author_email='', description=("A python package for distribution and transmission" From 3815c1671f8161498f11119fb2661ef0a42587a6 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 12:07:06 +0200 Subject: [PATCH 279/314] add sphinx-jsondomain --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 0c733bb6..f416bb31 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ numpy == 1.12.1 numpydoc == 0.7.0 sphinxcontrib-httpdomain aiohttp_jinja2 +sphinx-jsondomain From 7efb1e1ae774526fc41051989412f50143e30916 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 12:12:57 +0200 Subject: [PATCH 280/314] update settings --- ego/scenario_setting.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index b94f54c0..178458a9 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -10,8 +10,8 @@ "eTraGo": { "method": "lopf", "pf_post_lopf": false, - "start_snapshot": 1, - "end_snapshot" : 2, + "start_snapshot": 720, + "end_snapshot" : 730, "solver": "gurobi", "solver_options":{"threads":4, "method":2, @@ -29,7 +29,7 @@ "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": 100, + "network_clustering_kmeans": 30, "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, From 396e58e95012efbe33bf4e3eb5e3f7d860bf0714 Mon Sep 17 00:00:00 2001 From: maltesc Date: Wed, 18 Jul 2018 14:06:09 +0200 Subject: [PATCH 281/314] minor improvements --- ego/ego_main.py | 10 ++++---- ego/scenario_setting.json | 21 ++++++++-------- ego/tools/edisgo_integration.py | 24 ++++++++++++------ ego/tools/io.py | 43 ++++++++++++++++++++++++++------- 4 files changed, 66 insertions(+), 32 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index bb3c6f57..bef8cb0b 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -49,8 +49,8 @@ logger.info('Start calculation') ego = eGo(jsonpath='scenario_setting.json') - logger.info('Print results') - ego.etrago_line_loading() - print(ego.etrago.generator) - print(ego.etrago.storage_costs) - print(ego.etrago.operating_costs) +# logger.info('Print results') +# ego.etrago_line_loading() +# print(ego.etrago.generator) +# print(ego.etrago.storage_costs) +# print(ego.etrago.operating_costs) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index b94f54c0..add99a7e 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -1,10 +1,10 @@ { "global": { "eTraGo": true, - "eDisGo": false, + "eDisGo": true, "db": "oedb", - "result_id": 26, - "recover": true, + "result_id": null, + "recover": false, "gridversion": "v0.4.2" }, "eTraGo": { @@ -18,18 +18,18 @@ "crossover":1, "BarConvTol":"1.e-5", "FeasibilityTol":"1.e-5"}, - "scn_name": "NEP 2035", + "scn_name": "Status Quo", "scn_extension": null, "scn_decommissioning": null, "add_Belgium_Norway": false, "lpfile": false, "results": false, - "export": false, - "extendable": "['network','storages']", + "export": true, + "extendable": "[]", "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": 100, + "network_clustering_kmeans": false, "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, @@ -43,10 +43,9 @@ "eDisGo": { "specs": true, "ding0_files": "data/MV_grids/20180713110719", - "choice_mode": "manual", - "no_grids": null, - "manual_grids": [1729, 1730], - "scn_name": "NEP 2035", + "choice_mode": "cluster", + "no_grids": 2, + "manual_grids": [], "comments": "make a comment" } } diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 024a04b2..68d6a827 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -72,29 +72,34 @@ def __init__(self, json_file, etrago_network): Session = sessionmaker(bind=conn) self._session = Session() - # Json Inputs + # Genral Json Inputs self._json_file = json_file self._grid_version = self._json_file['global']['gridversion'] + # eTraGo args + self._etrago_args = self._json_file['eTraGo'] + self._scn_name = self._etrago_args['scn_name'] + # eDisGo args self._edisgo_args = self._json_file['eDisGo'] self._ding0_files = self._edisgo_args['ding0_files'] self._choice_mode = self._edisgo_args['choice_mode'] - - self._scn_name = self._edisgo_args['scn_name'] + + ## Scenario translation if self._scn_name == 'Status Quo': self._generator_scn = None elif self._scn_name == 'NEP 2035': self._generator_scn = 'nep2035' elif self._scn_name == 'eGo 100': self._generator_scn = 'ego100' - + + ## Versioning if self._grid_version is not None: self._versioned = True else: self._versioned = False - # eTraGo + # eTraGo Results (Input) self._etrago_network = etrago_network # eDisGo Results @@ -107,7 +112,7 @@ def __init__(self, json_file, etrago_network): @property def edisgo_grids(self): """ - Container for eDisGo grids, including all results :star: + Container for eDisGo grids, including all results Returns ------- @@ -293,10 +298,15 @@ def _run_edisgo(self, mv_grid_id): if self._generator_scn: logger.info( 'Importing generators for scenario {}'.format( - self._generator_scn) + self._scn_name) ) edisgo_grid.import_generators( generator_scenario=self._generator_scn) + else: + logger.info( + 'No generators imported for scenario {}'.format( + self._scn_name) + ) logger.info('Updating eDisGo timeseries with eTraGo values') edisgo_grid.network.timeseries = TimeSeriesControl( diff --git a/ego/tools/io.py b/ego/tools/io.py index 2b915aa4..6cff5330 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -306,24 +306,49 @@ class eDisGoResults(eTraGoResults): def __init__(self, jsonpath, *args, **kwargs): super(eDisGoResults, self).__init__(self, jsonpath, *args, **kwargs) - logger.info('eDisGoResults startet') - -# self.edisgo_networks = None - self.edisgo = pd.DataFrame() - + self._edisgo = None + self._edisgo_networks = None + if self.json_file['global']['eDisGo'] is True: - logger.info('Create eDisGo network') + logger.info('Create eDisGo networks') + + self._edisgo = pd.DataFrame() - self.edisgo_networks = EDisGoNetworks( + self._edisgo_networks = EDisGoNetworks( json_file=self.json_file, etrago_network=self.etrago_network) - self.edisgo.grid_costs = edisgo_grid_investment( - self.edisgo_networks, + self._edisgo.grid_costs = edisgo_grid_investment( + self._edisgo_networks, self.json_file ) + @property + def edisgo_networks(self): + """ + Container for eDisGo grids, including all results + + Returns + ------- + :obj:`dict` of :class:`edisgo.grid.network.EDisGo` + Dictionary of eDisGo objects, keyed by MV grid ID + + """ + return self._edisgo_networks + + @property + def edisgo(self): + """ + Contains basic informations about eDisGo + Returns + ------- + :pandas:`pandas.DataFrame` + + """ + return self._edisgo + + class eGo(eDisGoResults): """Main eGo module which including all results and main functionalities. From 8fe54163cad4930c81d4b206505a8f70655b6860 Mon Sep 17 00:00:00 2001 From: maltesc Date: Wed, 18 Jul 2018 16:30:02 +0200 Subject: [PATCH 282/314] documentation finished --- doc/api/modules.rst | 64 ++++++++++++++++----------------- ego/ego_main.py | 2 +- ego/scenario_setting.json | 12 +++---- ego/tools/economics.py | 19 +++++----- ego/tools/edisgo_integration.py | 35 +++++++++--------- ego/tools/io.py | 7 ++-- 6 files changed, 71 insertions(+), 68 deletions(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index 24df97f9..fd9b7c13 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -21,47 +21,47 @@ https://etrago.readthedocs.io/en/latest/api/etrago.html#module-etrago.appl .. json:object:: scenario_setting.json - Text Text scenario_setting.json + This file contains all input settings for the eGo tool. + :property global: Global settings that are valid for both eTraGo and eDisGo + :proptype global: :json:object:`global` + :property eTraGo: eTraGo settings, only valid for eTraGo run + :proptype eTraGo: :json:object:`eTraGo` + :property eDisGo: eDisGo settings, only valid for eDisGo runs + :proptype eDisGo: :json:object:`eDisGo` - :property global: Global settings - :proptype global: :json:object:`global setting` - :property eTraGo: eDisGo settings - :proptype eTraGo: :json:object:`eTraGo settings` - :property eDisGo: eDisGo settings - :proptype eDisGo: :json:object:`eDisGo settings` - - -.. json:object:: global settings - - Text Text - - - :property bool eTraGo: ``true`` or ``false`` - :property bool eDisGo: ``true`` or ``false``... - :property string db: Name od db, default="oedb" +.. json:object:: global + :property bool eTraGo: Decide if you want to run the eTraGo tool (HV/EHV grid optimization). + :property bool eDisGo: Decide if you want to run the eDisGo tool (MV grid optimiztaion). + :property string db: Name of your database (e.g.``''oedb''``). + :property bool recover: If ``true``, (previously calculated) eTraGo results are queried from your database (instead of performing a new run). + :property int result_id: ID of the (previeously calculated) eTraGo results that are queried if **recover** is set ``true``. + :property string gridversion: Version of the *open_eGo* input data-sets (e.g. ``''v0.4.2''``) -.. json:object:: eTraGo settings - - Text Text - - - :property bool pf_post_lopf: ``true`` or ``false`` - :property string method: "lopf - :property int start_snapshot: Start hour of calcualtion +.. json:object:: eTraGo + + This section of :json:object:`scenario_setting.json` contains all input parameters for the eTraGo tool. A description of the parameters can be found `here. `_ + + Please note that some parameters are already included in :json:object:`global` + + +.. json:object:: solver_options + + :property int threads: ??? -.. json:object:: eDisGo settings - - Text Text - +.. json:object:: eDisGo + + This section of :json:object:`scenario_setting.json` contains all input parameters for the eDisGo tool and the Clustering of MV grids. + + :property string ding0_files: Relative path to the MV grid files (created by `**ding0** `_) (e.g. ``''data/MV_grids/20180713110719''``) + :property string choice_mode: Mode that eGo uses to chose MV grids out of the files in **ding0_files** (e.g. ``''manual''``, ``''cluster''`` or ``''all''``). If ``''manual''`` is chosen, the parameter **manual_grids** must contain a list of the desired grids. If ``''cluster''`` is chosen, **no_grids** must specify the desired number of clusters. If ``''all''`` is chosen, all MV grids from **ding0_files** are calculated. + :property list manual_grids: List of MV grid ID's (*open_eGo* HV/MV substation ID's) + :property int no_grids: Number of MV grid clusters (from all files in **ding0_files**, a specified number of representative clusters is calculated) - :property pf_post_lopf: ``true`` or ``false`` - :property method: "lopf - :property int start_snapshot: Start hour of calcualtion ego_main.py diff --git a/ego/ego_main.py b/ego/ego_main.py index bef8cb0b..38b8846f 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -46,7 +46,7 @@ if __name__ == '__main__': # import scenario settings **args of eTraGo - logger.info('Start calculation') +# logger.info('Start calculation') ego = eGo(jsonpath='scenario_setting.json') # logger.info('Print results') diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index add99a7e..0bd91dcd 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -3,8 +3,8 @@ "eTraGo": true, "eDisGo": true, "db": "oedb", - "result_id": null, - "recover": false, + "recover": true, + "result_id": 26, "gridversion": "v0.4.2" }, "eTraGo": { @@ -18,13 +18,13 @@ "crossover":1, "BarConvTol":"1.e-5", "FeasibilityTol":"1.e-5"}, - "scn_name": "Status Quo", + "scn_name": "NEP 2035", "scn_extension": null, "scn_decommissioning": null, "add_Belgium_Norway": false, "lpfile": false, "results": false, - "export": true, + "export": false, "extendable": "[]", "generator_noise": true, "reproduce_noise": false, @@ -41,11 +41,9 @@ "comments": "eDisGo integration" }, "eDisGo": { - "specs": true, "ding0_files": "data/MV_grids/20180713110719", "choice_mode": "cluster", - "no_grids": 2, "manual_grids": [], - "comments": "make a comment" + "no_grids": 2 } } diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 1f077620..a4914757 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -310,7 +310,7 @@ def edisgo_grid_investment(edisgo_networks, json_file): p = 0.05 logger.warning('For all components T={} and p={} is used'.format(t, p)) - annuity_costs = pd.DataFrame(columns=['v_lev', 'annuity_costs']) + annuity_costs = pd.DataFrame(columns=['voltage_level', 'annuity_costs']) for key, value in edisgo_networks.edisgo_grids.items(): @@ -324,9 +324,9 @@ def edisgo_grid_investment(edisgo_networks, json_file): logger.info('No expansion costs for grid {}'.format(key)) continue - costs_single = costs_single.rename( - columns={'voltage_level': 'v_lev'} - ) +# costs_single = costs_single.rename( +# columns={'voltage_level': 'voltage_level'} +# ) choice = edisgo_networks.grid_choice weighting = choice.loc[ @@ -344,7 +344,7 @@ def edisgo_grid_investment(edisgo_networks, json_file): costs_single['annuity_costs'] = ( costs_single['annuity_costs'] * weighting) - costs_single = costs_single[['v_lev', 'annuity_costs']] + costs_single = costs_single[['voltage_level', 'annuity_costs']] annuity_costs = annuity_costs.append(costs_single, ignore_index=True) @@ -354,11 +354,14 @@ def edisgo_grid_investment(edisgo_networks, json_file): else: aggr_capital_costs = annuity_costs.groupby( - ['v_lev']).sum().reset_index() + ['voltage_level']).sum().reset_index() aggr_capital_costs = aggr_capital_costs.rename( - columns={'annuity_costs': 'grid_costs'} + columns={'annuity_costs': 'capital_cost'} ) - aggr_capital_costs['grid_costs'] = aggr_capital_costs['grid_costs'] * 1000 + aggr_capital_costs['capital_cost'] = ( + aggr_capital_costs['capital_cost'] + * 1000) # In eDisGo all costs are in kEuro, however + # eGo only takes Euro return aggr_capital_costs diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 68d6a827..fce8d7c5 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -250,7 +250,7 @@ def _run_edisgo_pool(self): ) count += 1 - def _run_edisgo(self, mv_grid_id): + def _run_edisgo(self, mv_grid_id, apply_curtailment=True): """ Performs a single eDisGo run @@ -316,22 +316,23 @@ def _run_edisgo(self, mv_grid_id): timeseries_load='demandlib', timeindex=specs['conv_dispatch'].index).timeseries - logger.info('Including Curtailment') - gens_df = tools.get_gen_info(edisgo_grid.network) - solar_wind_capacities = gens_df.groupby( - by=['type', 'weather_cell_id'] - )['nominal_capacity'].sum() - - curt_abs = pd.DataFrame(columns=specs['curtailment'].columns) - - for col in curt_abs: - curt_abs[col] = ( - specs['curtailment'][col] - * solar_wind_capacities[col]) - - edisgo_grid.curtail(curtailment_methodology='curtail_all', - timeseries_curtailment=curt_abs) -# Think about the other curtailment functions!!!! + if apply_curtailment: + logger.info('Including Curtailment') + gens_df = tools.get_gen_info(edisgo_grid.network) + solar_wind_capacities = gens_df.groupby( + by=['type', 'weather_cell_id'] + )['nominal_capacity'].sum() + + curt_abs = pd.DataFrame(columns=specs['curtailment'].columns) + + for col in curt_abs: + curt_abs[col] = ( + specs['curtailment'][col] + * solar_wind_capacities[col]) + + edisgo_grid.curtail(curtailment_methodology='curtail_all', + timeseries_curtailment=curt_abs) + # Think about the other curtailment functions!!!! edisgo_grid.analyze() diff --git a/ego/tools/io.py b/ego/tools/io.py index 793e7dee..0c5ca193 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -295,7 +295,7 @@ def __init__(self, jsonpath, *args, **kwargs): json_file=self.json_file, etrago_network=self.etrago_network) - self._edisgo.grid_costs = edisgo_grid_investment( + self._edisgo.grid_investment_costs = edisgo_grid_investment( self._edisgo_networks, self.json_file ) @@ -314,7 +314,7 @@ def edisgo_networks(self): return self._edisgo_networks @property - def edisgo(self): + def edisgo(self): """ Contains basic informations about eDisGo @@ -355,7 +355,8 @@ def __init__(self, jsonpath, *args, **kwargs): self.total_operation_costs = pd.DataFrame() # TODO pass - + + # write_results_to_db(): logging.info('Initialisation of eGo Results') From 3c184caf5eb84b102cc229171c243604f99180cc Mon Sep 17 00:00:00 2001 From: maltesc Date: Wed, 18 Jul 2018 16:32:59 +0200 Subject: [PATCH 283/314] documentation finished --- doc/api/modules.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index fd9b7c13..2cc7746b 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -48,16 +48,18 @@ https://etrago.readthedocs.io/en/latest/api/etrago.html#module-etrago.appl Please note that some parameters are already included in :json:object:`global` -.. json:object:: solver_options +.. + json:object:: solver_options :property int threads: ??? +.. .. json:object:: eDisGo This section of :json:object:`scenario_setting.json` contains all input parameters for the eDisGo tool and the Clustering of MV grids. - :property string ding0_files: Relative path to the MV grid files (created by `**ding0** `_) (e.g. ``''data/MV_grids/20180713110719''``) + :property string ding0_files: Relative path to the MV grid files (created by `ding0 `_) (e.g. ``''data/MV_grids/20180713110719''``) :property string choice_mode: Mode that eGo uses to chose MV grids out of the files in **ding0_files** (e.g. ``''manual''``, ``''cluster''`` or ``''all''``). If ``''manual''`` is chosen, the parameter **manual_grids** must contain a list of the desired grids. If ``''cluster''`` is chosen, **no_grids** must specify the desired number of clusters. If ``''all''`` is chosen, all MV grids from **ding0_files** are calculated. :property list manual_grids: List of MV grid ID's (*open_eGo* HV/MV substation ID's) :property int no_grids: Number of MV grid clusters (from all files in **ding0_files**, a specified number of representative clusters is calculated) From 9b078a91f50d2cbba1e1b4828cbe211458b89e1d Mon Sep 17 00:00:00 2001 From: maltesc Date: Wed, 18 Jul 2018 17:28:06 +0200 Subject: [PATCH 284/314] what's new finished --- doc/api/modules.rst | 7 ------- doc/whatsnew/v0-2-0.rst | 26 ++++---------------------- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index 2cc7746b..04923a79 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -48,13 +48,6 @@ https://etrago.readthedocs.io/en/latest/api/etrago.html#module-etrago.appl Please note that some parameters are already included in :json:object:`global` -.. - json:object:: solver_options - - :property int threads: ??? -.. - - .. json:object:: eDisGo This section of :json:object:`scenario_setting.json` contains all input parameters for the eDisGo tool and the Clustering of MV grids. diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index b0bfdfd3..212e1d86 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -1,18 +1,11 @@ Release v0.2.0 (July 18, 2018) ++++++++++++++++++++++++++++++ -Second release of the eGo application. +Fundamental structural changes of the eGo tool are included in this release. A new feature is the integration of the MV grid power flow simulations, performed by the tool `eDisGo. `_. Thereby, eGo can be used to perforem power flow simulations and optimizations for EHV, HV (*eTraGo*) and MV (*eDisGo*) grids. -New features have been included in this release. Major changes being the new -class structure and separation of methods into the given file structure. -Moreover the use of the Dataprocessing version ``'v0.4.1' ``and ``'v0.4.2'`` is -integrate. For eGo and the integration and interaction the app will depend on a -data version ``>= 'v0.4.1'`` in order to ensure the correct data handling. -Furthermore the inclusion of new methods and classes for eDisGo, storages etc. -is done. +Moreover, the use of the Dataprocessing versions ``''v0.4.1''`` and ``''v0.4.2''`` is supported. Please note, that this release is still under construction and only recommended for developers of the *open_eGo* project. -Please note, that this release is still under construction and not ready -for a normal use. +Furthermore, overall cost aggregation functions are available. Added features -------------- @@ -21,7 +14,7 @@ Added features * Moved classes of eGo from results.py to io.py * Move serveral function -* Introduce new files for edisgo handling +* Introduce new files for *eDisGo* handling * edisgo_integration.py * mv_cluster.py @@ -38,17 +31,6 @@ Added features * Fixed eTraGo scenario import of ``etrago_from_oedb()`` -ToDo's bis Release ------------------- - -* mv clustering for eDisGo / Ding0 grids -* cost manipulation / skalling of global costs -* all costs "over night" grid/storages (annuisiert) -* Plot der Gesamt investkosten -* operational costs edisgo ? | pro Ebene -* operational costs eTragGo | pro Ebene - - Notes ----- * As an external user you need to have and account on the From 79d8b0c82ef881766a19076b188426ee95591bbd Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 17:54:47 +0200 Subject: [PATCH 285/314] update investment costs --- ego/tools/economics.py | 114 +++++++++++------------------------------ 1 file changed, 30 insertions(+), 84 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 1f077620..c6131174 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -194,9 +194,9 @@ def etrago_grid_investment(network, json_file): Returns ------- - lines: :pandas:`pandas.Dataframe` - Dataframe with ``number_of_expansion``, ``s_nom_expansion`` and - ``grid_costs`` per calculated time steps + grid_investment_costs : :pandas:`pandas.Dataframe` + Dataframe with ``voltage_level``, ``number_of_expansion`` and + ``capital_cost`` per calculated time steps Example ------- @@ -205,15 +205,15 @@ def etrago_grid_investment(network, json_file): >>> from ego.tools.io import eGo >>> ego = eGo(jsonpath='scenario_setting.json') - >>> ego.etrago.grid_costs - - +--------+-------------------+------------+ - | v_level|number_of_expansion| grid_costs| - +========+===================+============+ - | ehv | 27.0 | 31514.1305 | - +--------+-------------------+------------+ - | hv | 0.0 | 0.0 | - +--------+-------------------+------------+ + >>> ego.etrago.grid_investment_costs + + +--------------+-------------------+--------------+ + | voltage_level|number_of_expansion| capital_cost| + +==============+===================+==============+ + | ehv | 27.0 | 31514.1305 | + +--------------+-------------------+--------------+ + | hv | 0.0 | 0.0 | + +--------------+-------------------+--------------+ """ # check settings for extendable @@ -228,19 +228,19 @@ def etrago_grid_investment(network, json_file): lines['s_nom_expansion'] = lines.s_nom_opt.subtract( lines.s_nom, axis='index') - lines['grid_costs'] = lines.s_nom_expansion.multiply( + lines['capital_cost'] = lines.s_nom_expansion.multiply( lines.capital_cost, axis='index') lines['number_of_expansion'] = lines.s_nom_expansion > 0.0 lines['time_step'] = get_time_steps(json_file) # add v_level - lines['v_level'] = 'unknown' + lines['voltage_level'] = 'unknown' ix_ehv = lines[lines['v_nom'] >= 380].index - lines.set_value(ix_ehv, 'v_level', 'ehv') + lines.set_value(ix_ehv, 'voltage_level', 'ehv') ix_hv = lines[(lines['v_nom'] <= 220) & (lines['v_nom'] >= 110)].index - lines.set_value(ix_hv, 'v_level', 'hv') + lines.set_value(ix_hv, 'voltage_level', 'hv') # based on eTraGo Function: # https://github.com/openego/eTraGo/blob/dev/etrago/tools/utilities.py#L651 @@ -249,39 +249,42 @@ def etrago_grid_investment(network, json_file): # get costs of transfomers trafos = network.transformers[['v_nom0', 'v_nom1', 'capital_cost', 's_nom_extendable', 's_nom', - 's_nom_opt']].reset_index() + 's_nom_opt']] + trafos.columns.name = "" + trafos.index.name = "" + trafos.reset_index() trafos['s_nom_extendable'] = trafos.s_nom_opt.subtract( trafos.s_nom, axis='index') - trafos['grid_costs'] = trafos.s_nom_extendable.multiply( + trafos['capital_cost'] = trafos.s_nom_extendable.multiply( trafos.capital_cost, axis='index') trafos['number_of_expansion'] = trafos.s_nom_extendable > 0.0 trafos['time_step'] = get_time_steps(json_file) # add v_level - trafos['v_level'] = 'unknown' + trafos['voltage_level'] = 'unknown' # TODO check ix_ehv = trafos[trafos['v_nom0'] >= 380].index - trafos.set_value(ix_ehv, 'v_level', 'ehv') + trafos.set_value(ix_ehv, 'voltage_level', 'ehv') ix_hv = trafos[(trafos['v_nom0'] <= 220) & (trafos['v_nom0'] >= 110)].index - trafos.set_value(ix_hv, 'v_level', 'hv') + trafos.set_value(ix_hv, 'voltage_level', 'hv') # aggregate lines and trafo - line = lines[['v_level', 'number_of_expansion', - 'grid_costs']].groupby('v_level').sum().reset_index() + line = lines[['voltage_level', + 'capital_cost']].groupby('voltage_level').sum().reset_index() - trafo = trafos[['v_level', 'number_of_expansion', - 'grid_costs']].groupby('v_level').sum().reset_index() + trafo = trafos[['voltage_level', + 'capital_cost']].groupby('voltage_level').sum().reset_index() # merge trafos and line frames = [line, trafo] - result = pd.concat(frames) + grid_investment_costs = pd.concat(frames) - return result + return grid_investment_costs # ToDo: add .agg({'number_of_expansion':lambda x: x.count(), # 's_nom_expansion': np.sum, @@ -366,7 +369,6 @@ def edisgo_grid_investment(edisgo_networks, json_file): def get_generator_investment(network, scn_name): """ Get investment costs per carrier/ generator. - """ # TODO - change values in csv # - add values to database @@ -397,59 +399,3 @@ def get_generator_investment(network, scn_name): gen_invest['p_nom'] * 1000 # in MW return gen_invest - - -def investment_costs(network): - """Return pandas DataFrame with investment costs of - - - - """ - # TODO Function outdated? - # TODO add edisgo - # etrago: - # Storages - # Line extentation - # edisgo: - # Line extentation - # Storage costs? - - etg = network - invest = pd.DataFrame() - - # storages - # get total storage investment costs - # unit of costs? - installed_storages = etg.storage_units[etg.storage_units.p_nom_opt != 0] - costs = sum(installed_storages.capital_cost * installed_storages.p_nom_opt) - invest = invest.append({'storage_costs': costs}, ignore_index=True) - - # get storage costs per voltage level - loc = etg.storage_units[etg.storage_units.p_nom_opt != 0]['bus'] - v_level = etg.buses.loc[loc, :]['v_nom'] - installed_storages = installed_storages.assign(v_nom=0) - - for i, k in v_level.iteritems(): - installed_storages.loc[installed_storages[installed_storages.bus == - i].index, 'v_nom'] = k - - storage_level = installed_storages.groupby('v_nom')['capital_cost'].sum() - - # Line extentation costs - # (eTraGo.lines.s_nom_opt - eTraGo.lines.s_nom) * eTraGo.lines.capital_cost - line_expen = (etg.lines.groupby('v_nom')['s_nom_opt'].sum() - - etg.lines.groupby('v_nom')['s_nom'].sum()) - - if line_expen.sum() <= 0: - print('Warning: !line extentation, set random costs for plotting!') - - lines_level = pd.DataFrame([[110., 722*np.exp(8)], [220., 822*np.exp(8)], - [380., 999*np.exp(9)]], columns=['v_nom', 'capital_cost']).\ - groupby('v_nom')['capital_cost'].sum() - - invest = invest.assign(line_costs=lines_level.sum()) - - # invest.transpose() - - # transfomers expantion costs - return invest From 8f075b666a56406178b5590e291089f60c4ff9c2 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 17:55:03 +0200 Subject: [PATCH 286/314] update import of investment costs --- ego/tools/io.py | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index f04a0c20..092e6168 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -47,7 +47,6 @@ etrago_operating_costs, etrago_grid_investment, edisgo_grid_investment, - investment_costs, get_generator_investment) from ego.tools.utilities import get_scenario_setting, get_time_steps from ego.tools.edisgo_integration import EDisGoNetworks @@ -181,7 +180,7 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago = pd.DataFrame() self.etrago.storage_investment_costs = etrago_storages_investment( - self.etrago_network) + self.etrago_network, self.json_file) self.etrago.storage_charges = etrago_storages(self.etrago_network) self.etrago.operating_costs = etrago_operating_costs( self.etrago_network) @@ -190,6 +189,7 @@ def __init__(self, jsonpath, *args, **kwargs): self.etrago.grid_investment_costs = etrago_grid_investment(self. etrago_network, self.json_file) + # # add functions direct # self.etrago_network.etrago_line_loading = etrago_line_loading @@ -326,10 +326,44 @@ def __init__(self, jsonpath, *args, **kwargs): # super().__init__(eDisGo) self.total = pd.DataFrame() # add total results here - self.total_investment_costs = pd.DataFrame() # TODO - self.total_operation_costs = pd.DataFrame() # TODO + #self.total_investment_costs = pd.DataFrame() + # self.total_operation_costs = pd.DataFrame() # TODO - pass + def total_investment_costs(self): + """ Get total investment costs of all voltage level for storages + and grid expansion + """ + + _grid_ehv = self.etrago.grid_investment_costs.capital_cost.sum() + + _storage = self.etrago.storage_investment_costs.capital_cost.sum() + # test data + _grid_mv_lv = pd.DataFrame(data=[{'voltage_level': 'mv', + 'capital_cost': 8823.22}, + {'voltage_level': 'lv', + 'capital_cost': 333.12}])\ + .capital_cost.sum() + # + self._total_inv_cost = pd.DataFrame(columns=['component', + 'capital_cost']) + self._total_inv_cost = self._total_inv_cost.append({'component': 'ehv hv grid', + 'capital_cost': _grid_ehv}, + ignore_index=True) + self._total_inv_cost = self._total_inv_cost.append({'component': 'storage', + 'capital_cost': _storage}, + ignore_index=True) + self._total_inv_cost = self._total_inv_cost.append({'component': 'mv lv grid', + 'capital_cost': _grid_mv_lv}, + ignore_index=True) + self.total_investment_cost = self._total_inv_cost + + def plot_total_investment_costs(self): + """ Plot total investment costs + """ + self.total_investment_costs() + + return self.total_investment_cost.plot.bar(x='component', + y='capital_cost', rot=1) # write_results_to_db(): logging.info('Initialisation of eGo Results') From df1a2881d4babcc322859e1fe4ff7eab1cfab184 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Wed, 18 Jul 2018 17:55:15 +0200 Subject: [PATCH 287/314] update functions --- ego/tools/storages.py | 52 +++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/ego/tools/storages.py b/ego/tools/storages.py index 80b289f3..b76ee34c 100644 --- a/ego/tools/storages.py +++ b/ego/tools/storages.py @@ -118,7 +118,7 @@ def etrago_storages(network): return storages -def etrago_storages_investment(network): +def etrago_storages_investment(network, json_file): """Calculate storage investment costs of eTraGo Parameters @@ -134,17 +134,41 @@ def etrago_storages_investment(network): Storage costs of selected snapshots in [EUR] """ - # provide storage installation costs - if sum(network.storage_units.p_nom_opt) != 0: + # check settings for extendable + if 'storages' not in json_file['eTraGo']['extendable']: + print("The optimizition was not using parameter 'extendable': storages") + print("No storages expantion costs from etrago") + + if 'storages' in json_file['eTraGo']['extendable']: + + # get v_nom + _bus = pd.DataFrame(network.buses['v_nom']) + _bus.reset_index(level=0, inplace=True) + + _storage = network.storage_units[network.storage_units.p_nom_opt != 0] + + # provide storage installation costs per voltage level installed_storages = \ - network.storage_units[network.storage_units.p_nom_opt != 0] - storage_costs = pd.DataFrame() - storage_costs = sum( - installed_storages.capital_cost * - installed_storages.p_nom_opt) - print( - "Investment costs for all storages in selected snapshots [EUR]:", - round( - storage_costs, - 2)) - return storage_costs + pd.merge(_storage, _bus, left_on='bus', right_on='index') + + installed_storages['investment_costs'] = (installed_storages. + capital_cost * + installed_storages.p_nom_opt) + + # add voltage_level + installed_storages['voltage_level'] = 'unknown' + + ix_ehv = installed_storages[installed_storages['v_nom'] >= 380].index + installed_storages.set_value(ix_ehv, 'voltage_level', 'ehv') + + ix_hv = installed_storages[(installed_storages['v_nom'] <= 220) & + (installed_storages['v_nom'] >= 110)].index + installed_storages.set_value(ix_hv, 'voltage_level', 'hv') + + storages_investment = installed_storages[ + ['voltage_level', 'investment_costs']].groupby('voltage_level').\ + sum().reset_index() + storages_investment = storages_investment.\ + rename(columns={'investment_costs': 'capital_cost'}) + + return storages_investment From db32746878db92a3e57c72f9309f8966253195a5 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 10:54:21 +0200 Subject: [PATCH 288/314] add new settings --- ego/scenario_setting.json | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 178458a9..569b62f5 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -1,10 +1,10 @@ { "global": { "eTraGo": true, - "eDisGo": false, + "eDisGo": true, "db": "oedb", - "result_id": 26, "recover": true, + "result_id": 26, "gridversion": "v0.4.2" }, "eTraGo": { @@ -25,11 +25,11 @@ "lpfile": false, "results": false, "export": false, - "extendable": "['network','storages']", + "extendable": "[]", "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": 30, + "network_clustering_kmeans": false, "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, @@ -41,12 +41,9 @@ "comments": "eDisGo integration" }, "eDisGo": { - "specs": true, "ding0_files": "data/MV_grids/20180713110719", - "choice_mode": "manual", - "no_grids": null, - "manual_grids": [1729, 1730], - "scn_name": "NEP 2035", - "comments": "make a comment" + "choice_mode": "cluster", + "manual_grids": [], + "no_grids": 2 } } From bfc3303f76461037ff26303a0c5cccd93b8a13a1 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 11:01:38 +0200 Subject: [PATCH 289/314] update file import --- ego/tools/economics.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index c6131174..9ccd24e0 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -376,8 +376,11 @@ def get_generator_investment(network, scn_name): etg = network - path = os.getcwd() + # TODO change it to utilities function + dirname = os.path.dirname(__file__) filename = 'investment_costs.csv' + path = os.path.join(dirname, filename) + invest = pd.DataFrame.from_csv(path + '/data/'+filename) if scn_name in ['SH Status Quo', 'Status Quo']: From e8cf59afb49d3aed2bd3d741c142c92f1d80665e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 11:02:10 +0200 Subject: [PATCH 290/314] update version --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index b8d5f597..543ca60f 100644 --- a/setup.py +++ b/setup.py @@ -27,10 +27,10 @@ def read(fname): include_package_data=True, install_requires=['egoio==0.4.1', 'eDisGo==0.0.3', - 'eTraGo==0.6', + 'eTraGo==0.6.1', 'pandas==0.20.3', 'pypsa==0.11.0fork', - 'sqlalchemy>= 1.0.15, <=1.2.0', + 'sqlalchemy<=1.1.4,>=1.0.15', 'geoalchemy2>= 0.3.0, <=0.4.0', 'pyproj==1.9.5.1', 'geopandas==0.3.0', From 95db0fabfe531d562893df9c569a36d1fa0916a5 Mon Sep 17 00:00:00 2001 From: maltesc Date: Thu, 19 Jul 2018 11:07:34 +0200 Subject: [PATCH 291/314] Status Quo generator import fixed :star: --- ego/scenario_setting.json | 7 ++++--- ego/tools/edisgo_integration.py | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 0bd91dcd..a536a2cc 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -3,8 +3,8 @@ "eTraGo": true, "eDisGo": true, "db": "oedb", - "recover": true, - "result_id": 26, + "recover": false, + "result_id": null, "gridversion": "v0.4.2" }, "eTraGo": { @@ -18,7 +18,7 @@ "crossover":1, "BarConvTol":"1.e-5", "FeasibilityTol":"1.e-5"}, - "scn_name": "NEP 2035", + "scn_name": "Status Quo", "scn_extension": null, "scn_decommissioning": null, "add_Belgium_Norway": false, @@ -30,6 +30,7 @@ "reproduce_noise": false, "minimize_loading": false, "network_clustering_kmeans": false, + "disaggregation": "uniform", "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index fce8d7c5..2c1aa358 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -286,7 +286,7 @@ def _run_edisgo(self, mv_grid_id, apply_curtailment=True): logger.error(msg) raise Exception(msg) - logger.info('Initial MV grid reinforcement (starting grid)') + logger.info('Initial MV grid reinforcement (worst-case anaylsis)') edisgo_grid = run_edisgo_basic( ding0_filepath=ding0_filepath, generator_scenario=None, @@ -306,8 +306,9 @@ def _run_edisgo(self, mv_grid_id, apply_curtailment=True): logger.info( 'No generators imported for scenario {}'.format( self._scn_name) - ) - + ) + edisgo_grid.network.pypsa = None + logger.info('Updating eDisGo timeseries with eTraGo values') edisgo_grid.network.timeseries = TimeSeriesControl( network=edisgo_grid.network, From e61aaae3126140e6380d2074f30df04285ba1bed Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 11:16:45 +0200 Subject: [PATCH 292/314] update import function --- ego/tools/economics.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index 6574f254..b0e4d39e 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -362,8 +362,8 @@ def edisgo_grid_investment(edisgo_networks, json_file): columns={'annuity_costs': 'capital_cost'} ) aggr_capital_costs['capital_cost'] = ( - aggr_capital_costs['capital_cost'] - * 1000) # In eDisGo all costs are in kEuro, however + aggr_capital_costs['capital_cost'] + * 1000) # In eDisGo all costs are in kEuro, however # eGo only takes Euro return aggr_capital_costs @@ -380,11 +380,15 @@ def get_generator_investment(network, scn_name): etg = network # TODO change it to utilities function - dirname = os.path.dirname(__file__) - filename = 'investment_costs.csv' - path = os.path.join(dirname, filename) - - invest = pd.DataFrame.from_csv(path + '/data/'+filename) + try: + dirname = os.path.dirname(__file__) + filename = 'investment_costs.csv' + path = os.path.join(dirname, filename) + invest = pd.DataFrame.from_csv(path + '~/data/'+filename) + except FileNotFoundError: + path = os.getcwd() + filename = 'investment_costs.csv' + invest = pd.DataFrame.from_csv(path + '/data/'+filename) if scn_name in ['SH Status Quo', 'Status Quo']: invest_scn = 'Status Quo' From c6202e6669861047e056f8425de19ec56787e409 Mon Sep 17 00:00:00 2001 From: maltesc Date: Thu, 19 Jul 2018 11:48:00 +0200 Subject: [PATCH 293/314] investment adjustments --- doc/whatsnew/v0-2-0.rst | 1 + ego/scenario_setting.json | 2 +- ego/tools/economics.py | 8 +++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index 212e1d86..b9223dbc 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -35,4 +35,5 @@ Notes ----- * As an external user you need to have and account on the `openenergy-platform.org/login `_ +* In future versions, all MV grids (*ding0* grids) will be queried from your database. However, in this version all MV grids have to be generated with the tool `ding0 `_ and stored in *eGo*'s *data* folder. * Total operational costs are missing in this release diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index a536a2cc..b24b192c 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -29,7 +29,7 @@ "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": false, + "network_clustering_kmeans": 5, "disaggregation": "uniform", "load_cluster": false, "network_clustering_ehv": false, diff --git a/ego/tools/economics.py b/ego/tools/economics.py index a4914757..631565c7 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -305,7 +305,13 @@ def edisgo_grid_investment(edisgo_networks, json_file): Dataframe containing annuity costs per voltage level """ - + etrago_args = json_file['eTraGo'] + scn_name = etrago_args['scn_name'] + + if scn_name == 'Status Quo': + logger.info('No eDisGo grid investment in Status Quo scenario') + return None + t = 40 p = 0.05 logger.warning('For all components T={} and p={} is used'.format(t, p)) From ecd8236097c8c2f542dbb2f5fb46c5259ed4cda5 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 13:49:04 +0200 Subject: [PATCH 294/314] update docu --- doc/api/modules.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/api/modules.rst b/doc/api/modules.rst index 04923a79..18acf603 100644 --- a/doc/api/modules.rst +++ b/doc/api/modules.rst @@ -16,8 +16,9 @@ Overview of modules scenario_settings.json ====================== -https://sphinx-jsondomain.readthedocs.io/en/latest/examples.html#github-user -https://etrago.readthedocs.io/en/latest/api/etrago.html#module-etrago.appl +With the ``scenario_settings.json`` file you set up your calcualtion. +The file can be found on +`github `_. .. json:object:: scenario_setting.json From de0e2b2d650335d4f6f121c4b93e4ccaa3393b10 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 13:52:12 +0200 Subject: [PATCH 295/314] update version --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index ebac9384..a8a92435 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -160,7 +160,7 @@ def setup(app): # built documents. # # The short X.Y version. -version = '0.2' +version = '0.2.0' # The full version, including alpha/beta/rc tags. release = '0.2.0' From fa7b7d765b86acb4e404fc84b0120cfd9d6a225f Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 14:32:20 +0200 Subject: [PATCH 296/314] add file for testing --- ego/run_test.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 ego/run_test.py diff --git a/ego/run_test.py b/ego/run_test.py new file mode 100644 index 00000000..1e4202a9 --- /dev/null +++ b/ego/run_test.py @@ -0,0 +1,42 @@ +from datetime import datetime +from tools.io import eGo +import sys +from pycallgraph import PyCallGraph +from pycallgraph.output import GraphvizOutput + + +def main(): + graphviz = GraphvizOutput() + graphviz.output_file = 'basic.png' + date = str(datetime.now()) + print(date) + with PyCallGraph(output=graphviz): + + ego = eGo(jsonpath='scenario_setting_solver_option.json') + + print(ego.etrago.storage_charges) + + print(ego.etrago.storage_investment_costs) + ego.etrago.storage_investment_costs.to_csv( + date+'etrago_storage_costs.csv') + print(ego.etrago.grid_investment_costs) + ego.etrago.grid_investment_costs.to_csv(date+'etrago_grid_costs.csv') + # test eTraGo plot and functions + + print(ego.edisgo.grid_investment_costs) + ego.edisgo.grid_investment_costs.to_csv(date+'edisgo_gridscosts.csv') + + ego.etrago_line_loading() + ego.etrago_stacked_gen() + ego.etrago_gen_dist() + ego.etrago_storage_distribution() + ego.etrago_voltage() + + # object size + print(sys.getsizeof(ego)) + + print(str(datetime.now())) + + +if __name__ == '__main__': + main() From 5e0eb4a788f111833a4cccd94bc706d0eb502f69 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 15:39:59 +0200 Subject: [PATCH 297/314] update cost function --- ego/tools/io.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index d471dd21..648c18d1 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -285,10 +285,10 @@ def __init__(self, jsonpath, *args, **kwargs): self._edisgo = None self._edisgo_networks = None - + if self.json_file['global']['eDisGo'] is True: logger.info('Create eDisGo networks') - + self._edisgo = pd.DataFrame() self._edisgo_networks = EDisGoNetworks( @@ -303,7 +303,7 @@ def __init__(self, jsonpath, *args, **kwargs): @property def edisgo_networks(self): """ - Container for eDisGo grids, including all results + Container for eDisGo grids, including all results Returns ------- @@ -314,7 +314,7 @@ def edisgo_networks(self): return self._edisgo_networks @property - def edisgo(self): + def edisgo(self): """ Contains basic informations about eDisGo @@ -324,8 +324,8 @@ def edisgo(self): """ return self._edisgo - - + + class eGo(eDisGoResults): """Main eGo module which including all results and main functionalities. @@ -363,21 +363,17 @@ def total_investment_costs(self): _storage = self.etrago.storage_investment_costs.capital_cost.sum() # test data - _grid_mv_lv = pd.DataFrame(data=[{'voltage_level': 'mv', - 'capital_cost': 8823.22}, - {'voltage_level': 'lv', - 'capital_cost': 333.12}])\ - .capital_cost.sum() + _grid_mv_lv = self.edisgo.grid_investment_costs.capital_cost.sum() # self._total_inv_cost = pd.DataFrame(columns=['component', 'capital_cost']) - self._total_inv_cost = self._total_inv_cost.append({'component': 'ehv hv grid', + self._total_inv_cost = self._total_inv_cost.append({'component': 'ehv-hv grid', 'capital_cost': _grid_ehv}, ignore_index=True) self._total_inv_cost = self._total_inv_cost.append({'component': 'storage', 'capital_cost': _storage}, ignore_index=True) - self._total_inv_cost = self._total_inv_cost.append({'component': 'mv lv grid', + self._total_inv_cost = self._total_inv_cost.append({'component': 'mv-lv grid', 'capital_cost': _grid_mv_lv}, ignore_index=True) self.total_investment_cost = self._total_inv_cost @@ -390,7 +386,6 @@ def plot_total_investment_costs(self): return self.total_investment_cost.plot.bar(x='component', y='capital_cost', rot=1) - # write_results_to_db(): logging.info('Initialisation of eGo Results') From d96535026b96d7afe71b0e4fefdbd97bdb1b93ea Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 15:40:36 +0200 Subject: [PATCH 298/314] update test file --- ego/run_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ego/run_test.py b/ego/run_test.py index 1e4202a9..398ec78c 100644 --- a/ego/run_test.py +++ b/ego/run_test.py @@ -18,13 +18,13 @@ def main(): print(ego.etrago.storage_investment_costs) ego.etrago.storage_investment_costs.to_csv( - date+'etrago_storage_costs.csv') + date+'__etrago_storage_costs.csv') print(ego.etrago.grid_investment_costs) - ego.etrago.grid_investment_costs.to_csv(date+'etrago_grid_costs.csv') + ego.etrago.grid_investment_costs.to_csv(date+'__etrago_grid_costs.csv') # test eTraGo plot and functions print(ego.edisgo.grid_investment_costs) - ego.edisgo.grid_investment_costs.to_csv(date+'edisgo_gridscosts.csv') + ego.edisgo.grid_investment_costs.to_csv(date+'__edisgo_gridscosts.csv') ego.etrago_line_loading() ego.etrago_stacked_gen() From a259f16f0113607d0d735b0755ff6f59ae4f79b9 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 15:51:54 +0200 Subject: [PATCH 299/314] fix link --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 9ea0166d..5ca90862 100644 --- a/README.rst +++ b/README.rst @@ -16,7 +16,7 @@ Integrated optimization of flexibility options and grid extension measures for power grids based on `eTraGo `_ and `eDisGo `_. The Documentation of the eGo tool can be found on -`openego.readthedocs.io `_ . .. contents:: @@ -31,7 +31,7 @@ Create a virtualenvironment (where you like it) and activate it: $ source venv/bin/activate $ cd venv $ pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo - --process-dependency-links) + --process-dependency-links LICENSE From ae367a0455e2b5308496d31a83270546717c759e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 16:32:53 +0200 Subject: [PATCH 300/314] update file --- ego/tools/io.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 648c18d1..db5bb06e 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -362,9 +362,7 @@ def total_investment_costs(self): _grid_ehv = self.etrago.grid_investment_costs.capital_cost.sum() _storage = self.etrago.storage_investment_costs.capital_cost.sum() - # test data - _grid_mv_lv = self.edisgo.grid_investment_costs.capital_cost.sum() - # + self._total_inv_cost = pd.DataFrame(columns=['component', 'capital_cost']) self._total_inv_cost = self._total_inv_cost.append({'component': 'ehv-hv grid', @@ -373,9 +371,15 @@ def total_investment_costs(self): self._total_inv_cost = self._total_inv_cost.append({'component': 'storage', 'capital_cost': _storage}, ignore_index=True) - self._total_inv_cost = self._total_inv_cost.append({'component': 'mv-lv grid', - 'capital_cost': _grid_mv_lv}, - ignore_index=True) + + if self.json_file['global']['eDisGo'] is True: + + _grid_mv_lv = self.edisgo.grid_investment_costs.capital_cost.sum() + + self._total_inv_cost = self._total_inv_cost.\ + append({'component': 'mv-lv grid', + 'capital_cost': _grid_mv_lv}, + ignore_index=True) self.total_investment_cost = self._total_inv_cost def plot_total_investment_costs(self): From 7b8ab9e44bcb629bf6050428f13575ea61a86683 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 16:41:13 +0200 Subject: [PATCH 301/314] update file --- ego/run_test.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ego/run_test.py b/ego/run_test.py index 398ec78c..edc35c50 100644 --- a/ego/run_test.py +++ b/ego/run_test.py @@ -3,6 +3,7 @@ import sys from pycallgraph import PyCallGraph from pycallgraph.output import GraphvizOutput +import pandas as pd def main(): @@ -17,14 +18,17 @@ def main(): print(ego.etrago.storage_charges) print(ego.etrago.storage_investment_costs) - ego.etrago.storage_investment_costs.to_csv( - date+'__etrago_storage_costs.csv') + + pd.DataFrame(ego.etrago.storage_investment_costs)\ + .to_csv(date+'__etrago_storage_costs.csv') print(ego.etrago.grid_investment_costs) - ego.etrago.grid_investment_costs.to_csv(date+'__etrago_grid_costs.csv') + pd.DataFrame(ego.etrago.grid_investment_costs).\ + to_csv(date+'__etrago_grid_costs.csv') # test eTraGo plot and functions print(ego.edisgo.grid_investment_costs) - ego.edisgo.grid_investment_costs.to_csv(date+'__edisgo_gridscosts.csv') + pd.DataFrame(ego.edisgo.grid_investment_costs)\ + .to_csv(date+'__edisgo_gridscosts.csv') ego.etrago_line_loading() ego.etrago_stacked_gen() From b974bfb84d51b8c947240eb6c49a49bff456dbb3 Mon Sep 17 00:00:00 2001 From: maltesc Date: Thu, 19 Jul 2018 16:55:04 +0200 Subject: [PATCH 302/314] Final adjustments for release --- ego/scenario_setting.json | 19 +++++++++---------- ego/tools/edisgo_integration.py | 1 - 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index b24b192c..2b79ecce 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -3,8 +3,8 @@ "eTraGo": true, "eDisGo": true, "db": "oedb", - "recover": false, - "result_id": null, + "recover": true, + "result_id": 26, "gridversion": "v0.4.2" }, "eTraGo": { @@ -18,7 +18,7 @@ "crossover":1, "BarConvTol":"1.e-5", "FeasibilityTol":"1.e-5"}, - "scn_name": "Status Quo", + "scn_name": "NEP 2035", "scn_extension": null, "scn_decommissioning": null, "add_Belgium_Norway": false, @@ -26,11 +26,10 @@ "results": false, "export": false, "extendable": "[]", - "generator_noise": true, + "generator_noise": false, "reproduce_noise": false, "minimize_loading": false, - "network_clustering_kmeans": 5, - "disaggregation": "uniform", + "network_clustering_kmeans": false, "load_cluster": false, "network_clustering_ehv": false, "snapshot_clustering": false, @@ -38,13 +37,13 @@ "skip_snapshots": false, "line_grouping": false, "branch_capacity_factor": 0.8, - "load_shedding": true, + "load_shedding": false, "comments": "eDisGo integration" }, "eDisGo": { "ding0_files": "data/MV_grids/20180713110719", - "choice_mode": "cluster", - "manual_grids": [], - "no_grids": 2 + "choice_mode": "manual", + "manual_grids": [1729], + "no_grids": null } } diff --git a/ego/tools/edisgo_integration.py b/ego/tools/edisgo_integration.py index 2c1aa358..d1c1f2b8 100644 --- a/ego/tools/edisgo_integration.py +++ b/ego/tools/edisgo_integration.py @@ -325,7 +325,6 @@ def _run_edisgo(self, mv_grid_id, apply_curtailment=True): )['nominal_capacity'].sum() curt_abs = pd.DataFrame(columns=specs['curtailment'].columns) - for col in curt_abs: curt_abs[col] = ( specs['curtailment'][col] From d18960eed97cea412f26b22aa837903e6b9b0224 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 17:00:04 +0200 Subject: [PATCH 303/314] update file --- README.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 5ca90862..e54d8d21 100644 --- a/README.rst +++ b/README.rst @@ -30,8 +30,7 @@ Create a virtualenvironment (where you like it) and activate it: $ virtualenv venv --clear -p python3.5 $ source venv/bin/activate $ cd venv - $ pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo - --process-dependency-links + $ pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo --process-dependency-links LICENSE From c3bf8af90f33300ee2692e972b745e5b7a1bcc1e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 17:09:38 +0200 Subject: [PATCH 304/314] update docu --- ego/tools/io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index db5bb06e..0206e912 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -490,7 +490,7 @@ def etrago_from_oedb(session, json_file): ---------- session : :sqlalchemy:`sqlalchemy.orm.session.Session` SQLAlchemy session to the OEDB - json_file : :obj:dict + json_file : :obj:`dict` Dictionary of the ``scenario_setting.json`` file Returns From 34a8fcbdcfd42eb3eb45a29f69acb6c0a5a2bfe6 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 17:09:45 +0200 Subject: [PATCH 305/314] update docu --- ego/tools/plots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/plots.py b/ego/tools/plots.py index 26db9454..d0895420 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -131,7 +131,7 @@ def igeoplot(network, session, tiles=None, geoloc=None, args=None): eTraGo network object compiled by :meth:`etrago.appl.etrago` tiles : str Folium background map style `None` as OSM or `Nasa` - geoloc : :obj:list + geoloc : :obj:`list` List which define center of map as (lon,lat) Returns From fbc1b61fec4c6f9f6b4cd9b24aefb6850ff33016 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 17:09:53 +0200 Subject: [PATCH 306/314] update docu --- ego/tools/specs.py | 126 ++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/ego/tools/specs.py b/ego/tools/specs.py index 04afd939..dfa5afbc 100644 --- a/ego/tools/specs.py +++ b/ego/tools/specs.py @@ -18,7 +18,7 @@ # File description """ -This files contains all eGo interface functions +This files contains all eGo interface functions """ __copyright__ = ("Europa-Universität Flensburg, " @@ -32,7 +32,7 @@ import pandas as pd import time if not 'READTHEDOCS' in os.environ: -# from sqlalchemy import distinct + # from sqlalchemy import distinct # This gives me the specific ORM classes. from egoio.db_tables import model_draft # from edisgo.grid.network import ETraGoSpecs @@ -43,7 +43,7 @@ # Functions -#def get_etragospecs_from_db(session, +# def get_etragospecs_from_db(session, # bus_id, # result_id): # """ @@ -374,14 +374,14 @@ # t5 = time.perf_counter() # performance.update({'Overall time': t5-t0}) # -## print("\n Conventional Dispatch (Normalized): \n", -## conv_dsptch_norm, +# print("\n Conventional Dispatch (Normalized): \n", +# conv_dsptch_norm, ## "\n\n Renewable Generators: \n", -## aggr_gens, +# aggr_gens, ## "\n\n Renewable Dispatch: \n", -## dispatch, +# dispatch, ## "\n\n Renewable Curtailment: \n", -## curtailment, "\n\n") +# curtailment, "\n\n") # # for keys, values in performance.items(): # print(keys, ": ", values) @@ -396,10 +396,10 @@ def get_etragospecs_direct(session, """ Reads eTraGo Results from Database and returns and returns the interface values as a dictionary of corresponding dataframes - + Parameters ---------- - session : sqla.orm.session.Session + session : sqlalchemy.orm.session.Session Handles conversations with the database. bus_id : int ID of the corresponding HV bus @@ -422,9 +422,10 @@ def get_etragospecs_direct(session, specs_meta_data.update({'TG Bus ID': bus_id}) # ormclass_result_meta = model_draft.__getattribute__('EgoGridPfHvResultMeta') - ormclass_gen_single = model_draft.__getattribute__('EgoSupplyPfGeneratorSingle') + ormclass_gen_single = model_draft.__getattribute__( + 'EgoSupplyPfGeneratorSingle') # ormclass_aggr_w = model_draft.t_ego_supply_aggr_weather_mview - + # __getattribute__( # 'ego_supply_aggr_weather_mview') logger.warning('Weather table taken from model_draft') @@ -455,23 +456,24 @@ def get_etragospecs_direct(session, weather_dpdnt = ['wind', 'solar', 'wind_onshore', 'wind_offshore'] # DF procesing - all_gens_df = etrago_network.generators[etrago_network.generators['bus'] == str(bus_id)] + all_gens_df = etrago_network.generators[etrago_network.generators['bus'] == str( + bus_id)] all_gens_df.reset_index(inplace=True) all_gens_df = all_gens_df.rename(columns={'index': 'generator_id'}) all_gens_df = all_gens_df[['generator_id', 'p_nom', 'p_nom_opt', 'carrier']] all_gens_df = all_gens_df.rename(columns={"carrier": "name"}) - - all_gens_df = all_gens_df[all_gens_df['name'] != 'wind_offshore'] + + all_gens_df = all_gens_df[all_gens_df['name'] != 'wind_offshore'] logger.warning('Wind offshore is disregarded in the interface') - + for index, row in all_gens_df.iterrows(): name = row['name'] if name == 'wind_onshore': all_gens_df.at[index, 'name'] = 'wind' logger.warning('wind onshore is renamed to wind') - -# print(all_gens_df) + +# print(all_gens_df) # names = [] # for index, row in all_gens_df.iterrows(): # carrier = row['carrier'] @@ -485,7 +487,7 @@ def get_etragospecs_direct(session, # names.append(name) # all_gens_df['name'] = names - + # all_gens_df = all_gens_df.drop(['carrier'], axis=1) # Conventionals @@ -499,8 +501,8 @@ def get_etragospecs_direct(session, index=snap_idx, columns=list(set(conv_df['name']))) conv_dsptch_abs = pd.DataFrame(0.0, - index=snap_idx, - columns=list(set(conv_df['name']))) + index=snap_idx, + columns=list(set(conv_df['name']))) for index, row in conv_df.iterrows(): generator_id = row['generator_id'] @@ -517,8 +519,6 @@ def get_etragospecs_direct(session, ren_df = all_gens_df[all_gens_df.name.isin(weather_dpdnt)] - - # w_ids = [] for index, row in ren_df.iterrows(): aggr_id = row['generator_id'] @@ -531,7 +531,7 @@ def get_etragospecs_direct(session, ) ren_df.at[index, 'w_id'] = w_id - + # w_ids.append(w_id) # ren_df = ren_df.assign(w_id=pd.Series(w_ids, index=ren_df.index)) @@ -547,26 +547,26 @@ def get_etragospecs_direct(session, aggr_gens.rename(columns={'p_nom': 'p_nom_aggr'}, inplace=True) aggr_gens['ren_id'] = aggr_gens.index - + # print(aggr_gens) ### Dispatch and Curteilment potential = pd.DataFrame(0.0, - index=snap_idx, - columns=aggr_gens['ren_id']) + index=snap_idx, + columns=aggr_gens['ren_id']) dispatch = pd.DataFrame(0.0, index=snap_idx, columns=aggr_gens['ren_id']) curtailment = pd.DataFrame(0.0, index=snap_idx, columns=aggr_gens['ren_id']) - + # potential_abs = pd.DataFrame(0.0, # index=snap_idx, # columns=aggr_gens['ren_id']) # dispatch_abs = pd.DataFrame(0.0, # index=snap_idx, -# columns=aggr_gens['ren_id']) +# columns=aggr_gens['ren_id']) # curtailment_abs = pd.DataFrame(0.0, # index=snap_idx, # columns=aggr_gens['ren_id']) @@ -593,71 +593,71 @@ def get_etragospecs_direct(session, # p_curt_tot_series = p_max_series - p_series # p_curt_norm_tot_series = p_max_norm_tot_series - p_norm_tot_series - - + potential[ren_id] = potential[ren_id] + p_max_norm_tot_series dispatch[ren_id] = dispatch[ren_id] + p_norm_tot_series # curtailment[ren_id] = curtailment[ren_id] + p_curt_norm_tot_series - + potential = potential.round(3) dispatch = dispatch.round(3) - + logger.warning('Rounding normalized values') curtailment = potential.sub(dispatch) - - + + # potential_abs[ren_id] = potential_abs[ren_id] + p_max_series # dispatch_abs[ren_id] = dispatch_abs[ren_id] + p_series # curtailment_abs[ren_id] = curtailment_abs[ren_id] + p_curt_tot_series - + # potential = dispatch + curtailment - + new_columns = [ (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) for col in potential.columns] - potential.columns = pd.MultiIndex.from_tuples(new_columns) - + potential.columns = pd.MultiIndex.from_tuples(new_columns) + new_columns = [ (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) for col in dispatch.columns] - dispatch.columns = pd.MultiIndex.from_tuples(new_columns) + dispatch.columns = pd.MultiIndex.from_tuples(new_columns) new_columns = [ (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) for col in curtailment.columns] - curtailment.columns = pd.MultiIndex.from_tuples(new_columns) + curtailment.columns = pd.MultiIndex.from_tuples(new_columns) # new_columns = [ # (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], # aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) # for col in potential_abs.columns] -# potential_abs.columns = pd.MultiIndex.from_tuples(new_columns) +# potential_abs.columns = pd.MultiIndex.from_tuples(new_columns) # # new_columns = [ # (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], # aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) # for col in dispatch_abs.columns] -# dispatch_abs.columns = pd.MultiIndex.from_tuples(new_columns) +# dispatch_abs.columns = pd.MultiIndex.from_tuples(new_columns) # # new_columns = [ # (aggr_gens[aggr_gens.ren_id == col].name.iloc[0], # aggr_gens[aggr_gens.ren_id == col].w_id.iloc[0]) # for col in curtailment_abs.columns] -# curtailment_abs.columns = pd.MultiIndex.from_tuples(new_columns) -# +# curtailment_abs.columns = pd.MultiIndex.from_tuples(new_columns) +# # potential_abs = potential_abs * 1000 # Absolute amounts in kW # dispatch_abs = dispatch_abs * 1000 # curtailment_abs = curtailment_abs * 1000 - + # Storage t3 = time.perf_counter() performance.update({'Renewable Dispatch and Curt.': t3-t2}) # Capactiy - stor_df = etrago_network.storage_units[etrago_network.storage_units['bus'] == str(bus_id)] + stor_df = etrago_network.storage_units[etrago_network.storage_units['bus'] == str( + bus_id)] stor_df.reset_index(inplace=True) stor_df = stor_df.rename(columns={'index': 'storage_id'}) stor_df = stor_df[[ @@ -668,7 +668,7 @@ def get_etragospecs_direct(session, 'carrier']] # print(stor_df) - + # names = [] # for index, row in stor_df.iterrows(): # carrier = row['carrier'] @@ -685,7 +685,7 @@ def get_etragospecs_direct(session, # stor_df = stor_df.drop(['carrier'], axis=1) stor_df = stor_df.rename(columns={"carrier": "name"}) - + stor_df['capacity_MWh'] = stor_df['p_nom_opt'] * stor_df['max_hours'] count_bat = 0 @@ -717,19 +717,19 @@ def get_etragospecs_direct(session, performance.update({'Storage Data Processing and Dispatch': t4-t3}) specs = { -# 'battery_capacity': battery_capacity, -# 'battery_active_power': battery_active_power, - 'conv_dispatch': conv_dsptch_norm, -# 'conv_dispatch_abs': conv_dsptch_abs, -# 'renewables': aggr_gens, - 'dispatch': dispatch, -# 'dispatch_abs': dispatch_abs, - 'potential': potential, -# 'potential_abs': potential_abs, - 'curtailment': curtailment#, -# 'curtailment_abs': curtailment_abs - } - + # 'battery_capacity': battery_capacity, + # 'battery_active_power': battery_active_power, + 'conv_dispatch': conv_dsptch_norm, + # 'conv_dispatch_abs': conv_dsptch_abs, + # 'renewables': aggr_gens, + 'dispatch': dispatch, + # 'dispatch_abs': dispatch_abs, + 'potential': potential, + # 'potential_abs': potential_abs, + 'curtailment': curtailment # , + # 'curtailment_abs': curtailment_abs + } + # specs = ETraGoSpecs(battery_capacity=battery_capacity, # battery_active_power=battery_active_power, # @@ -745,4 +745,4 @@ def get_etragospecs_direct(session, # for keys,values in performance.items(): # print(keys, ": ", values) - return specs \ No newline at end of file + return specs From ddc297eb85b0fa81b6d875206fd175ee01c94c28 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 17:10:01 +0200 Subject: [PATCH 307/314] update docu --- ego/tools/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/tools/utilities.py b/ego/tools/utilities.py index c587389a..bef24f1d 100644 --- a/ego/tools/utilities.py +++ b/ego/tools/utilities.py @@ -122,7 +122,7 @@ def get_time_steps(json_file): Parameters ---------- - json_file : :obj:dict + json_file : :obj:`dict` Dictionary of the ``scenario_setting.json`` file Returns From 6e737994477a05cb9ce6550f9775cdf347553fa9 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 17:21:25 +0200 Subject: [PATCH 308/314] add new version :ok_hand: --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 543ca60f..8bc8f3f0 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ def read(fname): package_dir={'ego': 'ego'}, include_package_data=True, install_requires=['egoio==0.4.1', - 'eDisGo==0.0.3', + 'eDisGo==0.0.4', 'eTraGo==0.6.1', 'pandas==0.20.3', 'pypsa==0.11.0fork', From 981a218c3405d00718d7b472f3ea207e084465a4 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 17:35:14 +0200 Subject: [PATCH 309/314] update run test --- ego/run_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ego/run_test.py b/ego/run_test.py index edc35c50..6bc8755c 100644 --- a/ego/run_test.py +++ b/ego/run_test.py @@ -22,13 +22,13 @@ def main(): pd.DataFrame(ego.etrago.storage_investment_costs)\ .to_csv(date+'__etrago_storage_costs.csv') print(ego.etrago.grid_investment_costs) - pd.DataFrame(ego.etrago.grid_investment_costs).\ - to_csv(date+'__etrago_grid_costs.csv') + etg_gic = pd.DataFrame(ego.etrago.grid_investment_costs) + etg_gic.to_csv(date+'__etrago_grid_costs.csv') # test eTraGo plot and functions print(ego.edisgo.grid_investment_costs) - pd.DataFrame(ego.edisgo.grid_investment_costs)\ - .to_csv(date+'__edisgo_gridscosts.csv') + edg_gic = pd.DataFrame(ego.edisgo.grid_investment_costs) + edg_gic.to_csv(date+'__edisgo_gridscosts.csv') ego.etrago_line_loading() ego.etrago_stacked_gen() From 91259b57a5ac3831103607a3a2926f7c818a3d6e Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 17:38:38 +0200 Subject: [PATCH 310/314] update doc :hammer: --- ego/tools/economics.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ego/tools/economics.py b/ego/tools/economics.py index b19098f8..06c7c18c 100644 --- a/ego/tools/economics.py +++ b/ego/tools/economics.py @@ -131,15 +131,15 @@ def etrago_operating_costs(network): >>> ego = eGo(jsonpath='scenario_setting.json') >>> ego.etrago.operating_costs - +-------------+-------------------+------------+ - | component |operation_costs | v_level | - +=============+===================+============+ - |biomass | 27.0 | | - +-------------+-------------------+------------+ - |line losses | 0.0 | | - +-------------+-------------------+------------+ - |wind_onshore | 0.0 | | - +-------------+-------------------+------------+ + +-------------+-------------------+------------------+ + | component |operation_costs | voltage_level | + +=============+===================+==================+ + |biomass | 27.0 | | + +-------------+-------------------+------------------+ + |line losses | 0.0 | | + +-------------+-------------------+------------------+ + |wind_onshore | 0.0 | | + +-------------+-------------------+------------------+ """ # TODO - change naming and function structure @@ -310,11 +310,11 @@ def edisgo_grid_investment(edisgo_networks, json_file): """ etrago_args = json_file['eTraGo'] scn_name = etrago_args['scn_name'] - + if scn_name == 'Status Quo': logger.info('No eDisGo grid investment in Status Quo scenario') return None - + t = 40 p = 0.05 logger.warning('For all components T={} and p={} is used'.format(t, p)) From f00d420926e309095d2797f9f9a83a03ecad7fe8 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 18:06:22 +0200 Subject: [PATCH 311/314] remove geopandas --- ego/tools/plots.py | 54 ++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/ego/tools/plots.py b/ego/tools/plots.py index d0895420..3fc1bb54 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -33,7 +33,7 @@ import pyproj as proj from shapely.geometry import Polygon, Point, MultiPolygon from geoalchemy2 import * - import geopandas as gpd + # import geopandas as gpd import folium from folium import plugins import branca.colormap as cm @@ -120,6 +120,8 @@ def make_all_plots(network): return +""" + def igeoplot(network, session, tiles=None, geoloc=None, args=None): """Plot function in order to display eGo results on leaflet OSM map. This function will open the results in your main Webbrowser @@ -127,16 +129,16 @@ def igeoplot(network, session, tiles=None, geoloc=None, args=None): Parameters ---------- - network_etrago: :class:`etrago.tools.io.NetworkScenario` - eTraGo network object compiled by :meth:`etrago.appl.etrago` - tiles : str + network_etrago:: class: `etrago.tools.io.NetworkScenario` + eTraGo network object compiled by: meth: `etrago.appl.etrago` + tiles: str Folium background map style `None` as OSM or `Nasa` - geoloc : :obj:`list` - List which define center of map as (lon,lat) + geoloc: : obj: `list` + List which define center of map as (lon, lat) Returns ------- - plot : html + plot: html HTML file with .js plot """ # TODO @@ -173,17 +175,17 @@ def igeoplot(network, session, tiles=None, geoloc=None, args=None): version = args['eTraGo']['gridversion'] for name, row in network.buses.iterrows(): - popup = """ Bus: {}
- carrier: {}
- control: {}
- type:{}
- v_nom:{}
- v_mag_pu_set:{}
- v_mag_pu_min:{}
- v_mag_pu_max:{}
- sub_network:{}
- Scenario: {}
- version: {}
+ popup = """ < b > Bus: < /b > {} < br > + carrier: {} < br > + control: {} < br > + type: {} < br > + v_nom: {} < br > + v_mag_pu_set: {} < br > + v_mag_pu_min: {} < br > + v_mag_pu_max: {} < br > + sub_network: {} < br > + Scenario: {} < br > + version: {} < br > """.format(row.name, scn_name, row['carrier'], row['control'], row['type'], row['v_nom'], row['v_mag_pu_set'], row['v_mag_pu_min'], row['v_mag_pu_max'], row['sub_network'], version) # add Popup values use HTML for formating @@ -296,8 +298,8 @@ def colormaper(): path = os.getcwd() url = path+"/map.html" webbrowser.open(url, new=new) - - +""" +""" def prepareGD(session, subst_id=None, version=None): """ """ @@ -322,7 +324,7 @@ def prepareGD(session, subst_id=None, version=None): Regions, columns=['subst_id', 'geometry'], crs=crs) return region - +""" def total_power_costs_plot(etrago_network): """ @@ -339,10 +341,10 @@ def total_power_costs_plot(etrago_network): """ - #import matplotlib.pyplot as plt + # import matplotlib.pyplot as plt plt.rcdefaults() - #import numpy as np - #import matplotlib.pyplot as plt + # import numpy as np + # import matplotlib.pyplot as plt fig, ax = plt.subplots() @@ -374,9 +376,9 @@ def plot_etrago_production(ego): Bar plot all etrago costs """ - #fig = plt.figure(figsize=(18,10), dpi=1600) + # fig = plt.figure(figsize=(18,10), dpi=1600) # plt.pie(ego.etrago['p'],autopct='%.1f') - #plt.title('Procentage of power production') + # plt.title('Procentage of power production') # max(ego.etrago['investment_costs'])/(1000*1000*1000) # T€/kW->M€/KW ->GW/MW From 2f9284e6133ef7d51d7fa0a3b1af5f7d1ab01a68 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 18:06:29 +0200 Subject: [PATCH 312/314] remove geopandas --- ego/tools/io.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 0206e912..9e681a56 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -29,7 +29,7 @@ if not 'READTHEDOCS' in os.environ: import pyproj as proj - import geopandas as gpd + #import geopandas as gpd from shapely.geometry import Polygon, Point, MultiPolygon from sqlalchemy import MetaData, create_engine, and_, func @@ -394,17 +394,18 @@ def plot_total_investment_costs(self): logging.info('Initialisation of eGo Results') +""" def geolocation_buses(network, session): """ - Use Geometries of buses x/y (lon/lat) and Polygons + Use Geometries of buses x/y(lon/lat) and Polygons of Countries from RenpassGisParameterRegion in order to locate the buses Parameters ---------- - network_etrago: :class:`etrago.tools.io.NetworkScenario` - eTraGo network object compiled by :meth:`etrago.appl.etrago` - session : :sqlalchemy:`sqlalchemy.orm.session.Session` + network_etrago: : class: `etrago.tools.io.NetworkScenario` + eTraGo network object compiled by: meth: `etrago.appl.etrago` + session: : sqlalchemy: `sqlalchemy.orm.session.Session < orm/session_basics.html >` SQLAlchemy session to the OEDB """ @@ -459,6 +460,7 @@ def geolocation_buses(network, session): session.close() return network +""" def results_to_excel(ego): From f142656abc40b0bde27b8e68d4faf1c67d4cba29 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 18:10:57 +0200 Subject: [PATCH 313/314] remove geopandas --- ego/tools/plots.py | 407 ++++++++++++++++++++++----------------------- 1 file changed, 202 insertions(+), 205 deletions(-) diff --git a/ego/tools/plots.py b/ego/tools/plots.py index 3fc1bb54..4d57175d 100644 --- a/ego/tools/plots.py +++ b/ego/tools/plots.py @@ -119,212 +119,209 @@ def make_all_plots(network): return +# +# def igeoplot(network, session, tiles=None, geoloc=None, args=None): +# """Plot function in order to display eGo results on leaflet OSM map. +# This function will open the results in your main Webbrowser +# +# Parameters +# ---------- +# +# network_etrago:: class: `etrago.tools.io.NetworkScenario` +# eTraGo network object compiled by: meth: `etrago.appl.etrago` +# tiles: str +# Folium background map style `None` as OSM or `Nasa` +# geoloc: : obj: `list` +# List which define center of map as (lon, lat) +# +# Returns +# ------- +# plot: html +# HTML file with .js plot +# """ +# # TODO +# # - implement eDisGo Polygons +# # - fix version problems of data +# # - use grid.ego_dp_hvmv_substation subst_id and otg_id +# # - use cluster or boxes to limit data volumn +# # - add Legend +# # - Map see: http://nbviewer.jupyter.org/gist/BibMartin/f153aa957ddc5fadc64929abdee9ff2e +# # - test cluster +# +# if geoloc is None: +# geoloc = [network.buses.y.mean(), network.buses.x.mean()] +# +# mp = folium.Map(tiles=None, location=geoloc, +# control_scale=True, zoom_start=6) +# +# # add Nasa light background +# if tiles == 'Nasa': +# tiles = 'https://map1.vis.earthdata.nasa.gov/wmts-webmerc/VIIRS_CityLights_2012/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.jpg' +# attr = ('© OpenStreetMap contributors, © CartoDB') +# +# folium.raster_layers.TileLayer(tiles=tiles, attr=attr).add_to(mp) +# else: +# folium.raster_layers.TileLayer('OpenStreetMap').add_to(mp) +# # 'Stamen Toner' OpenStreetMap +# +# # Legend name +# bus_group = folium.FeatureGroup(name='Buses') +# # add buses +# +# # get scenario name from args +# scn_name = args['eTraGo']['scn_name'] +# version = args['eTraGo']['gridversion'] +# +# for name, row in network.buses.iterrows(): +# popup = """ < b > Bus: < /b > {} < br > +# carrier: {} < br > +# control: {} < br > +# type: {} < br > +# v_nom: {} < br > +# v_mag_pu_set: {} < br > +# v_mag_pu_min: {} < br > +# v_mag_pu_max: {} < br > +# sub_network: {} < br > +# Scenario: {} < br > +# version: {} < br > +# """.format(row.name, scn_name, row['carrier'], +# row['control'], row['type'], row['v_nom'], row['v_mag_pu_set'], +# row['v_mag_pu_min'], row['v_mag_pu_max'], row['sub_network'], version) # add Popup values use HTML for formating +# folium.Marker([row["y"], row["x"]], popup=popup).add_to(bus_group) +# +# # Prepare lines +# line_group = folium.FeatureGroup(name='Lines') +# +# # get line Coordinates +# x0 = network.lines.bus0.map(network.buses.x) +# x1 = network.lines.bus1.map(network.buses.x) +# +# y0 = network.lines.bus0.map(network.buses.y) +# y1 = network.lines.bus1.map(network.buses.y) +# +# # get content +# text = network.lines +# +# # color map lines +# colormap = cm.linear.Set1.scale( +# text.s_nom.min(), text.s_nom.max()).to_step(6) +# +# def convert_to_hex(rgba_color): +# """ +# convert rgba colors to hex +# """ +# red = str(hex(int(rgba_color[0]*255)))[2:].capitalize() +# green = str(hex(int(rgba_color[1]*255)))[2:].capitalize() +# blue = str(hex(int(rgba_color[2]*255)))[2:].capitalize() +# +# if blue == '0': +# blue = '00' +# if red == '0': +# red = '00' +# if green == '0': +# green = '00' +# +# return '#' + red + green + blue +# +# # toDo add more parameter +# for line in network.lines.index: +# popup = """ Line: {}
+# version: {}
+# v_nom: {}
+# s_nom: {}
+# capital_cost: {}
+# g: {}
+# g_pu: {}
+# terrain_factor: {}
+# """.format(line, version, text.v_nom[line], +# text.s_nom[line], text.capital_cost[line], +# text.g[line], text.g_pu[line], +# text.terrain_factor[line] +# ) +# # ToDo make it more generic +# +# def colormaper(): +# l_color = [] +# if colormap.index[6] >= text.s_nom[line] > colormap.index[5]: +# l_color = colormap.colors[5] +# elif colormap.index[5] >= text.s_nom[line] > colormap.index[4]: +# l_color = colormap.colors[4] +# elif colormap.index[4] >= text.s_nom[line] > colormap.index[3]: +# l_color = colormap.colors[3] +# elif colormap.index[3] >= text.s_nom[line] > colormap.index[2]: +# l_color = colormap.colors[2] +# elif colormap.index[2] >= text.s_nom[line] > colormap.index[1]: +# l_color = colormap.colors[1] +# elif colormap.index[1] >= text.s_nom[line] >= colormap.index[0]: +# l_color = colormap.colors[0] +# else: +# l_color = (0., 0., 0., 1.) +# return l_color +# +# l_color = colormaper() +# +# folium.PolyLine(([y0[line], x0[line]], [y1[line], x1[line]]), +# popup=popup, color=convert_to_hex(l_color)).\ +# add_to(line_group) +# +# # add grod districs +# grid_group = folium.FeatureGroup(name='Grid district') +# subst_id = list(network.buses.index) +# district = prepareGD(session, subst_id, version) +# # todo does not work with k-mean Cluster +# # folium.GeoJson(district).add_to(grid_group) +# +# # add layers and others +# colormap.caption = 'Colormap of Lines s_nom' +# mp.add_child(colormap) +# +# # Add layer groups +# bus_group.add_to(mp) +# line_group.add_to(mp) +# grid_group.add_to(mp) +# folium.LayerControl().add_to(mp) +# +# plugins.Fullscreen( +# position='topright', +# title='Fullscreen', +# title_cancel='Exit me', +# force_separate_button=True).add_to(mp) +# +# # Save Map +# mp.save('map.html') +# +# # Display htm result from consol +# new = 2 # open in a new tab, if possible +# # open a public URL, in this case, the webbrowser docs +# path = os.getcwd() +# url = path+"/map.html" +# webbrowser.open(url, new=new) + +# def prepareGD(session, subst_id=None, version=None): +# """ +# """ +# +# if version == 'v0.2.11': +# query = session.query(EgoDpMvGriddistrict.subst_id, +# EgoDpMvGriddistrict.geom) +# +# Regions = [(subst_id, shape.to_shape(geom)) for subst_id, geom in +# query.filter(EgoDpMvGriddistrict.version == version, +# EgoDpMvGriddistrict.subst_id.in_(subst_id)).all()] +# # toDo add values of sub_id etc. to popup +# else: +# query = session.query(EgoGridMvGriddistrict.subst_id, +# EgoGridMvGriddistrict.geom) +# Regions = [(subst_id, shape.to_shape(geom)) for subst_id, geom in +# query.all()] +# +# region = pd.DataFrame(Regions, columns=['subst_id', 'geometry']) +# crs = {'init': 'epsg:3035'} +# region = gpd.GeoDataFrame( +# Regions, columns=['subst_id', 'geometry'], crs=crs) +# +# return region -""" - -def igeoplot(network, session, tiles=None, geoloc=None, args=None): - """Plot function in order to display eGo results on leaflet OSM map. - This function will open the results in your main Webbrowser - - Parameters - ---------- - - network_etrago:: class: `etrago.tools.io.NetworkScenario` - eTraGo network object compiled by: meth: `etrago.appl.etrago` - tiles: str - Folium background map style `None` as OSM or `Nasa` - geoloc: : obj: `list` - List which define center of map as (lon, lat) - - Returns - ------- - plot: html - HTML file with .js plot - """ - # TODO - # - implement eDisGo Polygons - # - fix version problems of data - # - use grid.ego_dp_hvmv_substation subst_id and otg_id - # - use cluster or boxes to limit data volumn - # - add Legend - # - Map see: http://nbviewer.jupyter.org/gist/BibMartin/f153aa957ddc5fadc64929abdee9ff2e - # - test cluster - - if geoloc is None: - geoloc = [network.buses.y.mean(), network.buses.x.mean()] - - mp = folium.Map(tiles=None, location=geoloc, - control_scale=True, zoom_start=6) - - # add Nasa light background - if tiles == 'Nasa': - tiles = 'https://map1.vis.earthdata.nasa.gov/wmts-webmerc/VIIRS_CityLights_2012/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.jpg' - attr = ('© OpenStreetMap contributors, © CartoDB') - - folium.raster_layers.TileLayer(tiles=tiles, attr=attr).add_to(mp) - else: - folium.raster_layers.TileLayer('OpenStreetMap').add_to(mp) - # 'Stamen Toner' OpenStreetMap - - # Legend name - bus_group = folium.FeatureGroup(name='Buses') - # add buses - - # get scenario name from args - scn_name = args['eTraGo']['scn_name'] - version = args['eTraGo']['gridversion'] - - for name, row in network.buses.iterrows(): - popup = """ < b > Bus: < /b > {} < br > - carrier: {} < br > - control: {} < br > - type: {} < br > - v_nom: {} < br > - v_mag_pu_set: {} < br > - v_mag_pu_min: {} < br > - v_mag_pu_max: {} < br > - sub_network: {} < br > - Scenario: {} < br > - version: {} < br > - """.format(row.name, scn_name, row['carrier'], - row['control'], row['type'], row['v_nom'], row['v_mag_pu_set'], - row['v_mag_pu_min'], row['v_mag_pu_max'], row['sub_network'], version) # add Popup values use HTML for formating - folium.Marker([row["y"], row["x"]], popup=popup).add_to(bus_group) - - # Prepare lines - line_group = folium.FeatureGroup(name='Lines') - - # get line Coordinates - x0 = network.lines.bus0.map(network.buses.x) - x1 = network.lines.bus1.map(network.buses.x) - - y0 = network.lines.bus0.map(network.buses.y) - y1 = network.lines.bus1.map(network.buses.y) - - # get content - text = network.lines - - # color map lines - colormap = cm.linear.Set1.scale( - text.s_nom.min(), text.s_nom.max()).to_step(6) - - def convert_to_hex(rgba_color): - """ - convert rgba colors to hex - """ - red = str(hex(int(rgba_color[0]*255)))[2:].capitalize() - green = str(hex(int(rgba_color[1]*255)))[2:].capitalize() - blue = str(hex(int(rgba_color[2]*255)))[2:].capitalize() - - if blue == '0': - blue = '00' - if red == '0': - red = '00' - if green == '0': - green = '00' - - return '#' + red + green + blue - - # toDo add more parameter - for line in network.lines.index: - popup = """ Line: {}
- version: {}
- v_nom: {}
- s_nom: {}
- capital_cost: {}
- g: {}
- g_pu: {}
- terrain_factor: {}
- """.format(line, version, text.v_nom[line], - text.s_nom[line], text.capital_cost[line], - text.g[line], text.g_pu[line], - text.terrain_factor[line] - ) - # ToDo make it more generic - - def colormaper(): - l_color = [] - if colormap.index[6] >= text.s_nom[line] > colormap.index[5]: - l_color = colormap.colors[5] - elif colormap.index[5] >= text.s_nom[line] > colormap.index[4]: - l_color = colormap.colors[4] - elif colormap.index[4] >= text.s_nom[line] > colormap.index[3]: - l_color = colormap.colors[3] - elif colormap.index[3] >= text.s_nom[line] > colormap.index[2]: - l_color = colormap.colors[2] - elif colormap.index[2] >= text.s_nom[line] > colormap.index[1]: - l_color = colormap.colors[1] - elif colormap.index[1] >= text.s_nom[line] >= colormap.index[0]: - l_color = colormap.colors[0] - else: - l_color = (0., 0., 0., 1.) - return l_color - - l_color = colormaper() - - folium.PolyLine(([y0[line], x0[line]], [y1[line], x1[line]]), - popup=popup, color=convert_to_hex(l_color)).\ - add_to(line_group) - - # add grod districs - grid_group = folium.FeatureGroup(name='Grid district') - subst_id = list(network.buses.index) - district = prepareGD(session, subst_id, version) - # todo does not work with k-mean Cluster - # folium.GeoJson(district).add_to(grid_group) - - # add layers and others - colormap.caption = 'Colormap of Lines s_nom' - mp.add_child(colormap) - - # Add layer groups - bus_group.add_to(mp) - line_group.add_to(mp) - grid_group.add_to(mp) - folium.LayerControl().add_to(mp) - - plugins.Fullscreen( - position='topright', - title='Fullscreen', - title_cancel='Exit me', - force_separate_button=True).add_to(mp) - - # Save Map - mp.save('map.html') - - # Display htm result from consol - new = 2 # open in a new tab, if possible - # open a public URL, in this case, the webbrowser docs - path = os.getcwd() - url = path+"/map.html" - webbrowser.open(url, new=new) -""" -""" -def prepareGD(session, subst_id=None, version=None): - """ - """ - - if version == 'v0.2.11': - query = session.query(EgoDpMvGriddistrict.subst_id, - EgoDpMvGriddistrict.geom) - - Regions = [(subst_id, shape.to_shape(geom)) for subst_id, geom in - query.filter(EgoDpMvGriddistrict.version == version, - EgoDpMvGriddistrict.subst_id.in_(subst_id)).all()] - # toDo add values of sub_id etc. to popup - else: - query = session.query(EgoGridMvGriddistrict.subst_id, - EgoGridMvGriddistrict.geom) - Regions = [(subst_id, shape.to_shape(geom)) for subst_id, geom in - query.all()] - - region = pd.DataFrame(Regions, columns=['subst_id', 'geometry']) - crs = {'init': 'epsg:3035'} - region = gpd.GeoDataFrame( - Regions, columns=['subst_id', 'geometry'], crs=crs) - - return region -""" def total_power_costs_plot(etrago_network): """ From 0069c9c94909d5fb97e693e431f6171b805e6945 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 19 Jul 2018 18:11:05 +0200 Subject: [PATCH 314/314] remove geopandas --- ego/tools/io.py | 132 ++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/ego/tools/io.py b/ego/tools/io.py index 9e681a56..843f6e3e 100644 --- a/ego/tools/io.py +++ b/ego/tools/io.py @@ -394,73 +394,71 @@ def plot_total_investment_costs(self): logging.info('Initialisation of eGo Results') -""" -def geolocation_buses(network, session): - """ - Use Geometries of buses x/y(lon/lat) and Polygons - of Countries from RenpassGisParameterRegion - in order to locate the buses - - Parameters - ---------- - network_etrago: : class: `etrago.tools.io.NetworkScenario` - eTraGo network object compiled by: meth: `etrago.appl.etrago` - session: : sqlalchemy: `sqlalchemy.orm.session.Session < orm/session_basics.html >` - SQLAlchemy session to the OEDB - - """ - # ToDo: check eTrago stack generation plots and other in order of adaptation - # Start db connetion - # get renpassG!S scenario data - - meta = MetaData() - meta.bind = session.bind - conn = meta.bind - # get db table - meta.reflect(bind=conn, schema='model_draft', - only=['renpass_gis_parameter_region']) - - # map to classes - Base = automap_base(metadata=meta) - Base.prepare() - RenpassGISRegion = Base.classes.renpass_gis_parameter_region - - # Define regions - region_id = ['DE', 'DK', 'FR', 'BE', 'LU', - 'NO', 'PL', 'CH', 'CZ', 'SE', 'NL'] - - query = session.query(RenpassGISRegion.gid, RenpassGISRegion.u_region_id, - RenpassGISRegion.stat_level, RenpassGISRegion.geom, - RenpassGISRegion.geom_point) - - # get regions by query and filter - Regions = [(gid, u_region_id, stat_level, shape.to_shape(geom), - shape.to_shape(geom_point)) for gid, u_region_id, stat_level, - geom, geom_point in query.filter(RenpassGISRegion.u_region_id. - in_(region_id)).all()] - - crs = {'init': 'epsg:4326'} - # transform lon lat to shapely Points and create GeoDataFrame - points = [Point(xy) for xy in zip(network.buses.x, network.buses.y)] - bus = gpd.GeoDataFrame(network.buses, crs=crs, geometry=points) - # Transform Countries Polygons as Regions - region = pd.DataFrame( - Regions, columns=['id', 'country', 'stat_level', 'Polygon', 'Point']) - re = gpd.GeoDataFrame(region, crs=crs, geometry=region['Polygon']) - # join regions and buses by geometry which intersects - busC = gpd.sjoin(bus, re, how='inner', op='intersects') - # busC - # Drop non used columns - busC = busC.drop(['index_right', 'Point', 'id', 'Polygon', - 'stat_level', 'geometry'], axis=1) - # add busC to eTraGo.buses - network.buses['country_code'] = busC['country'] - - # close session - session.close() - - return network -""" +# def geolocation_buses(network, session): +# """ +# Use Geometries of buses x/y(lon/lat) and Polygons +# of Countries from RenpassGisParameterRegion +# in order to locate the buses +# +# Parameters +# ---------- +# network_etrago: : class: `etrago.tools.io.NetworkScenario` +# eTraGo network object compiled by: meth: `etrago.appl.etrago` +# session: : sqlalchemy: `sqlalchemy.orm.session.Session < orm/session_basics.html >` +# SQLAlchemy session to the OEDB + # + # """ + # # ToDo: check eTrago stack generation plots and other in order of adaptation + # # Start db connetion + # # get renpassG!S scenario data + # + # meta = MetaData() + # meta.bind = session.bind + # conn = meta.bind + # # get db table + # meta.reflect(bind=conn, schema='model_draft', + # only=['renpass_gis_parameter_region']) + # + # # map to classes + # Base = automap_base(metadata=meta) + # Base.prepare() + # RenpassGISRegion = Base.classes.renpass_gis_parameter_region + # + # # Define regions + # region_id = ['DE', 'DK', 'FR', 'BE', 'LU', + # 'NO', 'PL', 'CH', 'CZ', 'SE', 'NL'] + # + # query = session.query(RenpassGISRegion.gid, RenpassGISRegion.u_region_id, + # RenpassGISRegion.stat_level, RenpassGISRegion.geom, + # RenpassGISRegion.geom_point) + # + # # get regions by query and filter + # Regions = [(gid, u_region_id, stat_level, shape.to_shape(geom), + # shape.to_shape(geom_point)) for gid, u_region_id, stat_level, + # geom, geom_point in query.filter(RenpassGISRegion.u_region_id. + # in_(region_id)).all()] + # + # crs = {'init': 'epsg:4326'} + # # transform lon lat to shapely Points and create GeoDataFrame + # points = [Point(xy) for xy in zip(network.buses.x, network.buses.y)] + # bus = gpd.GeoDataFrame(network.buses, crs=crs, geometry=points) + # # Transform Countries Polygons as Regions + # region = pd.DataFrame( + # Regions, columns=['id', 'country', 'stat_level', 'Polygon', 'Point']) + # re = gpd.GeoDataFrame(region, crs=crs, geometry=region['Polygon']) + # # join regions and buses by geometry which intersects + # busC = gpd.sjoin(bus, re, how='inner', op='intersects') + # # busC + # # Drop non used columns + # busC = busC.drop(['index_right', 'Point', 'id', 'Polygon', + # 'stat_level', 'geometry'], axis=1) + # # add busC to eTraGo.buses + # network.buses['country_code'] = busC['country'] + # + # # close session + # session.close() + # + # return network def results_to_excel(ego):

okeg;!B@VD?L(j)f7 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 g4P&)PW>#sYdSy<9;5X0oQ>wsMy5(4{S&;+5i9m literal 0 HcmV?d00001 From bc35580fcec53727152c209e97fb7cba9bdaf021 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 7 Jun 2018 07:23:56 +0200 Subject: [PATCH 030/314] change version of dialect --- ego/examples/tutorials/requirements.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ego/examples/tutorials/requirements.yml b/ego/examples/tutorials/requirements.yml index c273f8c3..a672c934 100644 --- a/ego/examples/tutorials/requirements.yml +++ b/ego/examples/tutorials/requirements.yml @@ -20,7 +20,7 @@ dependencies: - ding0==0.1.4 - "--editable=git+git@github.com:openego/eGo.git@dev#egg=eGo --process-dependency-links" - "--editable=git+git@github.com:openego/oedialect.git@master#egg=oedialect" - - "--editable=git+git@github.com:openego/ego.io.git@features/dialect#egg=egoio" + - "--editable=git+git@github.com:openego/ego.io.git@v0.4.0#egg=egoio" - "--editable=git+git@github.com:openego/PyPSA.git@dev#egg=pypsa" - "--editable=git+git@github.com:openego/eTraGo.git@0.5.1#egg=etrago" # eTraGo==0.5.1 - "--editable=git+git@github.com:openego/tsam.git@master#egg=tsam" From 1874d90fa98a36d2b50c1080e0d1bf27e8f7db8b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Thu, 21 Jun 2018 13:30:08 +0200 Subject: [PATCH 031/314] change comment and import --- ego/ego_main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 2de67657..23c28f8c 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -21,7 +21,8 @@ from tools.plots import (make_all_plots,plot_line_loading, plot_stacked_gen, add_coordinates, curtailment, gen_dist, storage_distribution, igeoplot) - # For importing geopandas you need to install spatialindex on your system http://github.com/libspatialindex/libspatialindex/wiki/1.-Getting-Started + # For importing geopandas you need to install spatialindex on your system + # http://github.com/libspatialindex/libspatialindex/wiki/1.-Getting-Started from tools.utilities import get_scenario_setting, get_time_steps from tools.io import geolocation_buses, etrago_from_oedb from tools.results import eGo From 3e4dab4bdf969e19fd5bb49a38bfc005e024338b Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:10:40 +0200 Subject: [PATCH 032/314] update new version --- setup.py | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/setup.py b/setup.py index 2d51320d..1f4a760e 100644 --- a/setup.py +++ b/setup.py @@ -1,22 +1,25 @@ -__copyright__ = "Flensburg University of Applied Sciences, Europa-Universität Flensburg, Centre for Sustainable Energy Systems, Next Energy, " +import os +from setuptools import find_packages, setup + +__copyright__ = ("Flensburg University of Applied Sciences, " + "Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" __author__ = "wolf_bunke" - -from setuptools import find_packages, setup -import os - setup(name='eGo', author='wolfbunke, maltesc', author_email='', - description='A python package for distribution and transmission grid analysis and optimization based eDisGo and eTraGo', + description=("A python package for distribution and transmission" + "grid analysis and optimization based eDisGo and eTraGo"), version='0.2.0', - url='https://github.com/openego/eGo', + url='https://github.com/openego/eGo', license="GNU Affero General Public License Version 3 (AGPL-3.0)", packages=find_packages(), include_package_data=True, - install_requires=['egoio == 0.3.0', + install_requires=['egoio == 0.4.1', 'eDisGo == 0.0.2', + 'eTraGo == 0.6', 'pandas ==0.20.3', 'sqlalchemy >= 1.0.15, <= 1.2.0', 'geoalchemy2 >= 0.3.0, <=0.4.0', @@ -24,20 +27,21 @@ 'geopandas==0.3.0', 'Rtree==0.8.3', 'plotly==2.2.3', - 'eTraGo==0.5.1', 'matplotlib >= 1.5.3, <=1.5.3'], - dependency_links=['git+https://git@github.com/openego/PyPSA.git@dev#egg=PyPSA', - 'git+https://git@github.com:python-visualization/folium.git@5739244acb9868d001032df288500a047b232857' - ], - extras_require={ - 'docs': [ - 'sphinx >= 1.4', - 'sphinx_rtd_theme', - 'sphinxcontrib-httpdomain']}, - package_data={ - 'ego': [ - os.path.join('*.json'), - os.path.join('tools','*.json'), - os.path.join('data','*.csv') ] - } - ) + dependency_links=[('git+https://git@github.com/openego/PyPSA.git' + '@dev#egg=pypsa-0.11.0fork'), + ('git+https://git@github.com:python-visualization/' + 'folium.git@dev#egg=folium') + ], + extras_require={ + 'docs': [ + 'sphinx >= 1.4', + 'sphinx_rtd_theme', + 'sphinxcontrib-httpdomain']}, + package_data={ + 'ego': [ + os.path.join('*.json'), + os.path.join('tools', '*.json'), + os.path.join('data', '*.csv')] + } + ) From f5c43de94478b8bb86ba904361a18496ab1a93ba Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:13:42 +0200 Subject: [PATCH 033/314] make file pep8 conform --- README.rst | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 3e2d816d..d095b770 100644 --- a/README.rst +++ b/README.rst @@ -2,14 +2,18 @@ :target: http://openego.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status -.. image:: https://openegoproject.files.wordpress.com/2017/02/open_ego_logo_breit.png?w=400 +.. image:: (https://openegoproject.files.wordpress.com/2017/02/ + open_ego_logo_breit.png?w=400) eGo ====== -Integrated optimization of flexibility options and grid extension measures for power grids based on eTraGo and eDisGo. +Integrated optimization of flexibility options and grid extension measures +for power grids based on eTraGo and eDisGo. -A speciality in this context is that transmission grids are described by the 380, 220 and 110 kV in Germany. The integration of the transmission grid (via eTraGo) and distribution grid (via eDisGo) is part of eGo. +A speciality in this context is that transmission grids are described by +the 380, 220 and 110 kV in Germany. The integration of the transmission grid +(via eTraGo) and distribution grid (via eDisGo) is part of eGo. .. contents:: @@ -23,7 +27,8 @@ Create a virtualenvironment (where you like it) and activate it: $ virtualenv eGo --clear -p python3.5 $ source venv/bin/activate - $ pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo --process-dependency-links --allow-all-external + $ (pip3 install -e git+https://github.com/openego/eGo@dev#egg=eGo + --process-dependency-links --allow-all-external) Copyleft @@ -31,4 +36,8 @@ Copyleft Code licensed under "GNU Affero General Public License Version 3 (AGPL-3.0)" It is a collaborative work with several copyright owner: -Cite as "eGo" © Flensburg University of Applied Sciences, Centre for Sustainable Energy Systems © Europa-Universität Flensburg, Centre for Sustainable Energy Systems © DLR Institute for Networked Energy Systems, © Reiner-Lemoine-Institute" +Cite as "eGo" © Flensburg University of Applied Sciences, +Centre for Sustainable Energy Systems © Europa-Universität Flensburg, +Centre for Sustainable Energy Systems +© DLR Institute for Networked Energy Systems, +© Reiner-Lemoine-Institute" From 4beb8dcd82f38012742c47361e46df823c66222d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:15:46 +0200 Subject: [PATCH 034/314] change file --- ego_dependencies.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ego_dependencies.txt b/ego_dependencies.txt index 050263f1..6f1d5191 100644 --- a/ego_dependencies.txt +++ b/ego_dependencies.txt @@ -1,8 +1,8 @@ # Packages of eGo including dependencies of eDisGo, etraGo and ding0 # cloned Packages of eGo: --e git+git@github.com:python-visualization/folium.git@5739244acb9868d001032df288500a047b232857#egg=folium --e git+https://github.com/openego/PyPSA.git@641f1e569966cfdd4cbd1c6810ade69d90a54286#egg=pypsa +-e git+git@github.com:python-visualization/folium.git@master#egg=folium +-e git+https://github.com/openego/PyPSA.git@dev#egg=pypsa # Used Packages and dependencies appdirs==1.4.3 @@ -20,7 +20,7 @@ demandlib==0.1.1 descartes==1.1.0 ding0==0.1.4 eDisGo==0.0.1 --e git+https://github.com/openego/eGo@43e840b79c00aba2d0eab9b6e632fe438ebb30a2#egg=eGo +-e git+https://github.com/openego/eGo@dev#egg=eGo egoio==0.3.0 ephem==3.7.6.0 eTraGo==0.5.1 From 70e9d31ee34442ce1c1d9e99ec9903f8076eb4bb Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:19:32 +0200 Subject: [PATCH 035/314] change version no. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1f4a760e..52747944 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ author_email='', description=("A python package for distribution and transmission" "grid analysis and optimization based eDisGo and eTraGo"), - version='0.2.0', + version='0.2', url='https://github.com/openego/eGo', license="GNU Affero General Public License Version 3 (AGPL-3.0)", packages=find_packages(), From 657b39350f23bf5fc0374fab75af9195fad5731d Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:19:56 +0200 Subject: [PATCH 036/314] auto pep8 changes --- ego/ego_main.py | 74 +++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 23c28f8c..80a2a435 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -8,19 +8,20 @@ to this database. """ -__copyright__ = "Flensburg University of Applied Sciences, Europa-Universität"\ - "Flensburg, Centre for Sustainable Energy Systems" +__copyright__ = ("Flensburg University of Applied Sciences, " + "Europa-Universität Flensburg, " + "Centre for Sustainable Energy Systems") __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" -__author__ = "wolfbunke, maltesc" +__author__ = "wolf_bunke,maltesc" import pandas as pd import os if not 'READTHEDOCS' in os.environ: from etrago.appl import etrago - from tools.plots import (make_all_plots,plot_line_loading, plot_stacked_gen, - add_coordinates, curtailment, gen_dist, - storage_distribution, igeoplot) + from tools.plots import (make_all_plots, plot_line_loading, plot_stacked_gen, + add_coordinates, curtailment, gen_dist, + storage_distribution, igeoplot) # For importing geopandas you need to install spatialindex on your system # http://github.com/libspatialindex/libspatialindex/wiki/1.-Getting-Started from tools.utilities import get_scenario_setting, get_time_steps @@ -35,15 +36,16 @@ logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) -## Logging -logging.basicConfig(format='%(asctime)s %(message)s',level=logging.INFO) +# Logging +logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) ego_logger = logging.getLogger('ego') fh = logging.FileHandler('ego.log', mode='w') fh.setLevel(logging.INFO) -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +formatter = logging.Formatter('%(asctime)s - %(name)s - \ + %(levelname)s - %(message)s') fh.setFormatter(formatter) logger.addHandler(fh) @@ -55,7 +57,7 @@ logging.info('Start calculation') args = get_scenario_setting(json_file='scenario_setting.json') logger.info("calculation settings are used \ - with Metadata: \n %s" %args) + with Metadata: \n %s" % args) try: conn = db.connection(section=args['global']['db']) @@ -73,51 +75,46 @@ # add country code to bus and geometry (shapely) # eTraGo.buses = eTraGo.buses.drop(['country_code','geometry'], axis=1) - #test = geolocation_buses(network = eTraGo, session) + # test = geolocation_buses(network = eTraGo, session) # make a line loading plot eGo.eTraGo.plot_line_loading(eTraGo) - # get eTraGo results form db if args['global']['recover']: - eTraGo = etrago_from_oedb(session,args) + eTraGo = etrago_from_oedb(session, args) # use eTraGo results from ego calculations if true # ToDo make function edisgo_direct_specs() - - if args['eDisGo']['direct_specs']: # ToDo: add this to utilities.py logging.info('Retrieving Specs') - bus_id = 27574 #23971 + bus_id = 27574 # 23971 from ego.tools.specs import get_etragospecs_direct, get_mvgrid_from_bus_id from egoio.db_tables import model_draft specs = get_etragospecs_direct(session, bus_id, eTraGo, args) - - # ToDo make loop for all bus ids # make function which links bus_id (subst_id) if args['eDisGo']['specs']: - logging.info('Retrieving Specs') # ToDo make it more generic # ToDo iteration of grids # ToDo move part as function to utilities or specs - bus_id = 27574 #23971 + bus_id = 27574 # 23971 result_id = args['global']['result_id'] from ego.tools.specs import get_etragospecs_from_db, get_mvgrid_from_bus_id from egoio.db_tables import model_draft specs = get_etragospecs_from_db(session, bus_id, result_id) - mv_grid = get_mvgrid_from_bus_id(session, bus_id) # This function can be used to call the correct MV grid + # This function can be used to call the correct MV grid + mv_grid = get_mvgrid_from_bus_id(session, bus_id) if args['global']['eDisGo']: @@ -125,7 +122,8 @@ # ToDo move part as function to utilities or specs from datetime import datetime - from edisgo.grid.network import Network, Scenario, TimeSeries, Results, ETraGoSpecs + from edisgo.grid.network import (Network, Scenario, + TimeSeries, Results, ETraGoSpecs) import networkx as nx import matplotlib.pyplot as plt @@ -136,29 +134,29 @@ #mv_grid = open(file_path) mv_grid_id = file_path.split('_')[-1].split('.')[0] - power_flow = (datetime(2011, 5, 26, 12), datetime(2011, 5, 26, 13)) # Where retrieve from? Database or specs? + # Where retrieve from? Database or specs? + power_flow = (datetime(2011, 5, 26, 12), datetime(2011, 5, 26, 13)) timeindex = pd.date_range(power_flow[0], power_flow[1], freq='H') scenario = Scenario(etrago_specs=specs, - power_flow=(), - mv_grid_id=mv_grid_id, - scenario_name= args['eTraGo']['scn_name']) + power_flow=(), + mv_grid_id=mv_grid_id, + scenario_name=args['eTraGo']['scn_name']) network = Network.import_from_ding0(file_path, - id=mv_grid_id, - scenario=scenario) + id=mv_grid_id, + scenario=scenario) # check SQ MV grid network.analyze() - network.results.v_res(#nodes=network.mv_grid.graph.nodes(), - level='mv') + network.results.v_res( # nodes=network.mv_grid.graph.nodes(), + level='mv') network.results.s_res() # A status quo grid (without new renewable gens) should not need reinforcement network.reinforce() - nx.draw(network.mv_grid.graph) plt.draw() plt.show() @@ -167,21 +165,19 @@ costs = network.results.grid_expansion_costs print(costs) - - # make interactive plot with folium #logging.info('Starting interactive plot') - #igeoplot(network=eTraGo, session=session, args=args) # ToDo: add eDisGo results + # igeoplot(network=eTraGo, session=session, args=args) # ToDo: add eDisGo results # calculate power plant dispatch without grid utilization (either in pypsa or in renpassgis) # result queries...call functions from utilities - ## total system costs of transmission grid vs. total system costs of all distribution grids results in overall total - ## details on total system costs: - ## existing plants: usage, costs for each technology - ## newly installed plants (storages, grid measures) with size, location, usage, costs - ## grid losses: amount and costs + # total system costs of transmission grid vs. total system costs of all distribution grids results in overall total + # details on total system costs: + # existing plants: usage, costs for each technology + # newly installed plants (storages, grid measures) with size, location, usage, costs + # grid losses: amount and costs # possible aggregation of results From 2ad88d328a741629696d11e9d83fd6d4e79a8604 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:21:40 +0200 Subject: [PATCH 037/314] update file --- ego/__init__.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/ego/__init__.py b/ego/__init__.py index e894ccc1..34b38237 100644 --- a/ego/__init__.py +++ b/ego/__init__.py @@ -1,23 +1,21 @@ -## This program is free software; you can redistribute it and/or -## modify it under the terms of the GNU Affero General Public License as -## published by the Free Software Foundation; either version 3 of the -## License, or (at your option) any later version. +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU Affero General Public License for more details. -## You should have received a copy of the GNU Affero General Public License -## along with this program. If not, see . +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . - -__version__ = "0.0.1" -__copyright__ = "Europa-Universität Flensburg, Centre for Sustainable Energy Systems" +__version__ = "0.2" +__copyright__ = ("Europa-Universität Flensburg, " + " Centre for Sustainable Energy Systems") __license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)" __author__ = "wolf_bunke" import logging logging.basicConfig(level=logging.INFO) - - From ca8d7e456e23d0f5321201ce4c4f16da101b5eb7 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:23:08 +0200 Subject: [PATCH 038/314] change to pypsa fork --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 52747944..2075f9b7 100644 --- a/setup.py +++ b/setup.py @@ -21,6 +21,7 @@ 'eDisGo == 0.0.2', 'eTraGo == 0.6', 'pandas ==0.20.3', + 'pypsa==0.11.0fork', 'sqlalchemy >= 1.0.15, <= 1.2.0', 'geoalchemy2 >= 0.3.0, <=0.4.0', 'pyproj == 1.9.5.1', From f2e34eddf0138b7f8c990f681a0233b2eeb1a046 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:26:42 +0200 Subject: [PATCH 039/314] test folium install --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 2075f9b7..c7cbe764 100644 --- a/setup.py +++ b/setup.py @@ -28,11 +28,12 @@ 'geopandas==0.3.0', 'Rtree==0.8.3', 'plotly==2.2.3', + 'folium ==folium-master' 'matplotlib >= 1.5.3, <=1.5.3'], dependency_links=[('git+https://git@github.com/openego/PyPSA.git' '@dev#egg=pypsa-0.11.0fork'), ('git+https://git@github.com:python-visualization/' - 'folium.git@dev#egg=folium') + 'folium.git@dev#egg=folium-master') ], extras_require={ 'docs': [ From 6a3f3a1703893f3eee7d27ed2e67ea29e56b8b63 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:29:41 +0200 Subject: [PATCH 040/314] update file --- setup.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index c7cbe764..a372ca1a 100644 --- a/setup.py +++ b/setup.py @@ -26,10 +26,11 @@ 'geoalchemy2 >= 0.3.0, <=0.4.0', 'pyproj == 1.9.5.1', 'geopandas==0.3.0', + 'folium ==folium-master', + 'matplotlib >= 1.5.3, <=1.5.3', 'Rtree==0.8.3', - 'plotly==2.2.3', - 'folium ==folium-master' - 'matplotlib >= 1.5.3, <=1.5.3'], + 'plotly==2.2.3' + ], dependency_links=[('git+https://git@github.com/openego/PyPSA.git' '@dev#egg=pypsa-0.11.0fork'), ('git+https://git@github.com:python-visualization/' From 74eea3399d2eac5167892d00075590ece68f97ab Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:42:27 +0200 Subject: [PATCH 041/314] remove folium --- setup.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/setup.py b/setup.py index a372ca1a..0c8f7410 100644 --- a/setup.py +++ b/setup.py @@ -26,15 +26,12 @@ 'geoalchemy2 >= 0.3.0, <=0.4.0', 'pyproj == 1.9.5.1', 'geopandas==0.3.0', - 'folium ==folium-master', 'matplotlib >= 1.5.3, <=1.5.3', 'Rtree==0.8.3', 'plotly==2.2.3' ], dependency_links=[('git+https://git@github.com/openego/PyPSA.git' - '@dev#egg=pypsa-0.11.0fork'), - ('git+https://git@github.com:python-visualization/' - 'folium.git@dev#egg=folium-master') + '@dev#egg=pypsa-0.11.0fork') ], extras_require={ 'docs': [ From f00b493c88e99d85c4fa0c6f763f7be50f9600d0 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 10:53:04 +0200 Subject: [PATCH 042/314] change and add 0.6 eTraGo parameters --- ego/scenario_setting.json | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index bb19ccdf..164a99d9 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -9,22 +9,28 @@ }, "eTraGo": { "db": "oedb", - "gridversion": null, + "gridversion": "v0.3.2", "method": "lopf", "pf_post_lopf": false, "start_snapshot": 1, "end_snapshot" : 5, - "scn_name": "SH NEP 2035", "solver": "gurobi", + "solver_options": "{}", + "scn_name": "SH NEP 2035", + "scn_extension": null, + "scn_decommissioning": null, + "add_Belgium_Norway": false, "lpfile": false, "results": false, "export": false, - "storage_extendable": false, + "extendable": "['storages']", "generator_noise": true, "reproduce_noise": false, "minimize_loading": false, - "k_mean_clustering": false, - "network_clustering": false, + "network_clustering_kmeans": 20, + "load_cluster": false, + "network_clustering_ehv": false, + "snapshot_clustering": false, "parallelisation": false, "skip_snapshots": false, "line_grouping": false, From b2208154645068fde66055c352417d5f8fb6c4a4 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 11:16:08 +0200 Subject: [PATCH 043/314] add text --- doc/whatsnew/v0-2-0.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/whatsnew/v0-2-0.rst b/doc/whatsnew/v0-2-0.rst index 9477834a..70884b2e 100644 --- a/doc/whatsnew/v0-2-0.rst +++ b/doc/whatsnew/v0-2-0.rst @@ -10,7 +10,11 @@ and is still under construction and not ready for a normal use. Added features -------------- -* +* Clean and restructured eGo classes and functions +* add eTraGo features zo eGo +* add eDisGo ... +* updated to eTraGo 0.6, eDisGo 0.2 and ego.io v0.4.2 version +* implemented pep8 style Notes ----- From 5c6a8fa378dd0f42367c4de3ec65fe8f122b1a46 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 13:39:06 +0200 Subject: [PATCH 044/314] update settings --- ego/scenario_setting.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ego/scenario_setting.json b/ego/scenario_setting.json index 164a99d9..c4f351b4 100644 --- a/ego/scenario_setting.json +++ b/ego/scenario_setting.json @@ -1,22 +1,22 @@ { "global": { "eTraGo": true, - "eDisGo": true, + "eDisGo": false, "db": "oedb", - "result_id": 359, + "result_id": null, "recover": false, - "gridversion": null + "gridversion": "v0.4.2" }, "eTraGo": { "db": "oedb", - "gridversion": "v0.3.2", + "gridversion": "v0.4.2", "method": "lopf", "pf_post_lopf": false, "start_snapshot": 1, "end_snapshot" : 5, "solver": "gurobi", - "solver_options": "{}", - "scn_name": "SH NEP 2035", + "solver_options":{}, + "scn_name": "NEP 2035", "scn_extension": null, "scn_decommissioning": null, "add_Belgium_Norway": false, @@ -24,7 +24,7 @@ "results": false, "export": false, "extendable": "['storages']", - "generator_noise": true, + "generator_noise": false, "reproduce_noise": false, "minimize_loading": false, "network_clustering_kmeans": 20, From 2c9525a685732076d814229ec74da72328427222 Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 13:39:43 +0200 Subject: [PATCH 045/314] update file --- ego/ego_main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ego/ego_main.py b/ego/ego_main.py index 80a2a435..763c0276 100644 --- a/ego/ego_main.py +++ b/ego/ego_main.py @@ -92,7 +92,7 @@ logging.info('Retrieving Specs') - bus_id = 27574 # 23971 + bus_id = 25402 # 23971 from ego.tools.specs import get_etragospecs_direct, get_mvgrid_from_bus_id from egoio.db_tables import model_draft @@ -106,7 +106,7 @@ # ToDo make it more generic # ToDo iteration of grids # ToDo move part as function to utilities or specs - bus_id = 27574 # 23971 + bus_id = 25402 # 27574 # 23971 result_id = args['global']['result_id'] from ego.tools.specs import get_etragospecs_from_db, get_mvgrid_from_bus_id From a5eb9c55bcd620a9f43d4a56e15cc060ede62eab Mon Sep 17 00:00:00 2001 From: wolfbunke Date: Mon, 2 Jul 2018 13:47:40 +0200 Subject: [PATCH 046/314] delete old data file --- ego/data/ding0_grids/ding0_grids__1802.pkl | Bin 722022 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ego/data/ding0_grids/ding0_grids__1802.pkl diff --git a/ego/data/ding0_grids/ding0_grids__1802.pkl b/ego/data/ding0_grids/ding0_grids__1802.pkl deleted file mode 100644 index 13ec630780f31d4ca23837af1afb7b6b5f421d46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 722022 zcmeEP2YeJ&_YEDRCK+yqS4(?wdDdH%B!qDlRFT(Wh5Y zxr$^@h$IdzS2OpfCp(_iqdMLs8E=}Cmz|ZBRZua#ps2iTddZBqy-cr)@NkhosFITmk`jJM3m+mMT^NM(6xRidQ4EZ!=w2|Q!st=)zziy~!VRZ?CV-ylDp zExt*KaH6WR>wZ<`@eRXyEx3H8Dk+X{l-C^P0sZ?8inno_O_a=vsBqbgNM(HE{P-qC z72&etaHZ@{uadIj$ec)Jui|hbLSAKdL0RO`g1vQhEW_FHwi%Z3(c2~Co94)7pxJP| zeY9;9t`0fT_C;k?vnuAgtDaR=nkWe?6`q@oJx9M)CR9~XB0JvEWo2V4B^uu>H>)Pz zX+)F4c;^N2&7JrbIk`=8o7Tj))WqV%+=@tce5<^s*z@s&<6Gxux2mt_W2VZF}YdE__jGCnwC|@w?kw2mxynlig!!IcPLymqAl8SKNm0SGpbou zR=j&6zGI>6QdxLbB%U)t%F|UO9`7+h)|;3Y-)TZsD!#K5-zAzeA=<r%o=_t06fVk-Ps)*9n^aI%J}bVzaGm%8f_d@D zkwpB!LP!Ck$aCTcMc2HQl9|~K^HXo@!O8d(w_zL;m55Kx%@Qe8CL$H_{M;sJQrF8X z;)momNBad%d|D(w9ya?|$o(sF;>EImxy@7Yh~C4J!SU(t9?o#$QS4#VpBRaF2~uEM z*9lMsKS>vcp6_DkA6)#aHXcjFXBLL@FG*5N7R=9fG13VnFu(TV77l@r}R zdO(!@TB-Xr;l!)L$@uKNme`y=z4{L5)i-`;Bw9#?RmSJ##}7-! z56{VKjU{HyPz7*T#*;;bRV5gX$||!fOG}C{m>hvlYQ|CINGE=jG%!0{T7~wiqs3L> zs>($CXm>m)z~B=!cr_&6J>^^lJNyO(P7cy(GgLKd?7@> zD97!9W33K2jva8k6F-3+(5fbWqIAGX?rzBlbaEbsrK|%A%HpTUu8b|16`oU&h{jKi zx&j;*KTU)GFDsoJKLfpZrtZbFocP(;2I%gboG8>5bww6E zBsUw{I@gJx2W_37W5jg{R?>Ew1T<ks`N3+*@2su)CDFhOkq3QB@F?9d;Ia5!%?}gA|9c~!?_Ppmqt@k|dfQznuIdsp; zPTeQ9SRJCb!wsvwzo`_#jXgcspcHmV`{A#ZQuZc#{E1W~{lLW1E7{9e%Y@iprtzN9}K(slM+j4u}Ccf>&w#1j^ZEn0dqsH~ndr-S2cdRj9 zyES*NFBg&pPqvMYjK; z6aNT-B~=lQ?H?CLkBM>+-v&#Kn_Muf98;`<8JJ&JVxpul`L8Ufh$!*IKarvR(`5WJ zduab0L;Dx{kbG%%%2(Xtubuce+~Qs}@o%M5zRQupx^Mh@!G7@{1pCK-6dVx$NpN8N zXTd@7Uj%oJ|0*~*{+r;C`0p|q?b|2*hg;|y|I;n>Q_NGh++Q{E$^%qWuRKsS^U8x% zbFaLsYT=a!tCn7Qh-ziZ{rafZUb(N@z$^Dt*Tv4^~@v z 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 v2F24lUZL<3+m@(0szpyb>kIX4MA=iFJc>G`wK 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