Skip to content

Commit

Permalink
Merge branch 'master' into set_scenario_variables
Browse files Browse the repository at this point in the history
  • Loading branch information
oluchee committed Dec 2, 2019
2 parents 18f2bba + 4e3c798 commit 9e81350
Show file tree
Hide file tree
Showing 17 changed files with 1,703 additions and 3,126 deletions.
1 change: 1 addition & 0 deletions .coveralls.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
repo_token: fZ0YDYNip5i0bzs2LTPY84oOzTJe01ppc
20 changes: 20 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: flake8
args: ['--max-line-length=120'] # default of Black
- id: requirements-txt-fixer
- id: check-merge-conflict
- id: name-tests-test
args: ['--django']
- repo: https://github.com/pre-commit/mirrors-isort
rev: v4.3.4
hooks:
- id: isort
21 changes: 11 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
sudo: false
language: python
python:
- "3.6"
- "3.6"

# easiest way of getting rtree
before_install:
- sudo apt update
- sudo apt install libspatialindex-dev
- sudo apt update
- sudo apt install libspatialindex-dev

# command to install dependencies
install:
- pip install wheel
- pip install Rtree
- pip install -r requirements.txt
- python setup.py develop

# command to run tests
- pip install wheel Rtree
- pip install -r requirements.txt
- pip install -U pytest pytest-cov coverage coveralls
- python setup.py develop
script:
- pytest
- pytest --cov onsset --cov-report html --verbose
after_success:
- coveralls
39 changes: 21 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
onsset
=================================
onsset : Open Source Spatial Electrification Tool
=================================================

[![PyPI version](https://badge.fury.io/py/gridfinder.svg)](https://test.pypi.org/project/gep-onsset/)
[![PyPI version](https://badge.fury.io/py/gridfinder.svg)](https://pypi.org/project/onsset/)
[![Build Status](https://travis-ci.com/OnSSET/onsset.svg?branch=master)](https://travis-ci.com/OnSSET/onsset)
[![Coverage Status](https://coveralls.io/repos/github/OnSSET/onsset/badge.svg?branch=master)](https://coveralls.io/github/OnSSET/onsset?branch=master)
[![Documentation Status](https://readthedocs.org/projects/onsset/badge/?version=latest)](https://onsset.readthedocs.io/en/latest/?badge=latest)

Documentation: https://onsset.readthedocs.io/en/latest/index.html#

# Scope

This repository contains the source code of the Open Source Spatial Electrification Tool ([OnSSET](http://www.onsset.org/)). The repository also includes sample test files available in ```.\test_data``` and sample output files available in ```.\sample_output```.
This repository contains the source code of the Open Source Spatial Electrification Tool
([OnSSET](http://www.onsset.org/)).


The repository also includes sample test files available in ```.\test_data```
and sample output files available in ```.\sample_output```.

## Installation

**Requirements**
### Requirements

OnSSET requires Python > 3.5 with the following packages installed:
- et-xmlfile
Expand All @@ -27,27 +31,26 @@ OnSSET requires Python > 3.5 with the following packages installed:
- xlrd


**Install with pip**
### Install with pip

Install onsset from the Python Packaging Index (PyPI):

```
pip install onsset
```

**Install from GitHub**
### Install from GitHub

Download or clone the repository and install the package in `develop` (editable) mode:
Download or clone the repository and install the package in `develop`
(editable) mode:

```
git clone https://github.com/onsset/onsset.git
cd gep-onsset
cd onsset
python setup.py develop
```

The use of GEP generator requires also installation of
- IPython
- jupyter
- matplotlib
- seaborn

## Contact
For more information regarding the tool, its functionality and implementation please visit https://www.onsset.org or contact the development team at seap@desa.kth.se.
For more information regarding the tool, its functionality and implementation
please visit https://www.onsset.org or contact the development team
at seap@desa.kth.se.
11 changes: 6 additions & 5 deletions onsset/gui_runner.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# This file runs either the calibration or scenario modules in the runner file,
# and asks the user to browse to the necessary input files
"""Provides a GUI for the user to choose input files
This file runs either the calibration or scenario modules in the runner file,
and asks the user to browse to the necessary input files
"""

import os
import tkinter as tk
from tkinter import filedialog, messagebox
import pandas as pd
from runner import *
from runner import calibration, scenario

root = tk.Tk()
root.withdraw()
Expand Down Expand Up @@ -41,4 +43,3 @@
summary_folder = filedialog.askdirectory()

scenario(specs_path, calibrated_csv_path, results_folder, summary_folder)

81 changes: 24 additions & 57 deletions onsset/onsset.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
# Author: KTH dESA Last modified by Andreas Sahlberg
# Date: 05 June 2019
# Python version: 3.5

import os
import logging
import pandas as pd
from math import ceil, pi, exp, log, sqrt, radians, cos, sin, asin
from math import asin, ceil, cos, exp, log, pi, radians, sin, sqrt

# from pyproj import Proj
import numpy as np
from collections import defaultdict

# from IPython.display import Markdown
import pandas as pd

logging.basicConfig(format='%(asctime)s\t\t%(message)s', level=logging.DEBUG)

# General
LHV_DIESEL = 9.9445485 # (kWh/l) lower heating value
HOURS_PER_YEAR = 8760

# Columns in settlements file must match these exactly
SET_COUNTRY = 'Country' # This cannot be changed, lots of code will break
SET_X_DEG = 'X_deg' # Coordinates in degrees
Expand Down Expand Up @@ -108,43 +97,9 @@
SET_SA_DIESEL_FUEL = 'SADieselFuelCost'
SET_MG_DIESEL_FUEL = 'MGDieselFuelCost'

# Columns in the specs file must match these exactly
SPE_COUNTRY = 'Country'
SPE_POP = 'PopStartYear' # The actual population in the base year
SPE_URBAN = 'UrbanRatioStartYear' # The ratio of urban population (range 0 - 1) in base year
SPE_POP_FUTURE = 'PopEndYear'
SPE_URBAN_FUTURE = 'UrbanRatioEndYear'
SPE_URBAN_MODELLED = 'UrbanRatioModelled' # The urban ratio in the model after calibration (for comparison)
SPE_URBAN_CUTOFF = 'UrbanCutOff' # The urban cutoff population calirated by the model, in people per km2
SPE_URBAN_GROWTH = 'UrbanGrowth' # The urban growth rate as a simple multplier (urban pop future / urban pop present)
SPE_RURAL_GROWTH = 'RuralGrowth' # Same as for urban
SPE_NUM_PEOPLE_PER_HH_RURAL = 'NumPeoplePerHHRural'
SPE_NUM_PEOPLE_PER_HH_URBAN = 'NumPeoplePerHHUrban'
SPE_DIESEL_PRICE_LOW = 'DieselPriceLow' # Diesel price in USD/litre
SPE_DIESEL_PRICE_HIGH = 'DieselPriceHigh' # Same, with a high forecast var
SPE_GRID_PRICE = 'GridPrice' # Grid price of electricity in USD/kWh
SPE_GRID_CAPACITY_INVESTMENT = 'GridCapacityInvestmentCost' # grid capacity investments costs from TEMBA USD/kW
SPE_GRID_LOSSES = 'GridLosses' # As a ratio (0 - 1)
SPE_BASE_TO_PEAK = 'BaseToPeak' # As a ratio (0 - 1)
SPE_EXISTING_GRID_COST_RATIO = 'ExistingGridCostRatio'
SPE_MAX_GRID_DIST = 'MaxGridDist'
SPE_ELEC = 'ElecActual' # Actual current percentage electrified population (0 - 1)
SPE_ELEC_MODELLED = 'ElecModelled' # The modelled version after calibration (for comparison)
SPE_ELEC_URBAN = 'Urban_elec_ratio' # Actual electrification for urban areas
SPE_ELEC_RURAL = 'Rural_elec_ratio' # Actual electrification for rural areas
SPE_MIN_NIGHT_LIGHTS = 'MinNightLights'
SPE_MAX_GRID_EXTENSION_DIST = 'MaxGridExtensionDist'
SPE_MAX_ROAD_DIST = 'MaxRoadDist'
SPE_POP_CUTOFF1 = 'PopCutOffRoundOne'
SPE_POP_CUTOFF2 = 'PopCutOffRoundTwo'
SPE_ELEC_LIMIT = "ElecLimit"
SPE_INVEST_LIMIT = "InvestmentLimit"
SPE_DIST_TO_TRANS = "DistToTrans"

SPE_START_YEAR = "StartYear"
SPE_END_YEAR = "EndYEar"
SPE_TIMESTEP = "TimeStep"

# General
LHV_DIESEL = 9.9445485 # (kWh/l) lower heating value
HOURS_PER_YEAR = 8760

class Technology:
"""
Expand Down Expand Up @@ -196,6 +151,8 @@ def set_default_values(cls, base_year, start_year, end_year, discount_rate, HV_l
max_nodes_per_serv_trans=300, MV_LV_sub_station_type=400, MV_LV_sub_station_cost=10000,
MV_MV_sub_station_cost=10000, HV_LV_sub_station_type=1000, HV_LV_sub_station_cost=25000,
HV_MV_sub_station_cost=25000, power_factor=0.9, load_moment=9643):
"""Initialises the class with parameter values common to all Technologies
"""
cls.base_year = base_year
cls.start_year = start_year
cls.end_year = end_year
Expand Down Expand Up @@ -700,10 +657,6 @@ def classify_slope(row):
else:
return 1

def set_penalty(row):
classification = row[SET_COMBINED_CLASSIFICATION]
return 1 + (exp(0.85 * abs(1 - classification)) - 1) / 100

logging.info('Classify road dist')
self.df[SET_ROAD_DIST_CLASSIFIED] = self.df.apply(classify_road_dist, axis=1)

Expand All @@ -726,8 +679,22 @@ def set_penalty(row):
0.15 * self.df[SET_ELEVATION_CLASSIFIED] +
0.30 * self.df[SET_SLOPE_CLASSIFIED])

def set_penalty(classification):
"""Return penalty value based on classification
Arguments
---------
classification : float
Returns
-------
float
"""
return 1 + (exp(0.85 * abs(1 - classification)) - 1) / 100

logging.info('Grid penalty')
self.df[SET_GRID_PENALTY] = self.df.apply(set_penalty, axis=1)
self.df[SET_GRID_PENALTY] = self.df[SET_COMBINED_CLASSIFICATION].apply(set_penalty)

def calc_wind_cfs(self):
"""
Expand Down Expand Up @@ -920,7 +887,7 @@ def elec_current_and_future(self, elec_actual, elec_actual_urban, elec_actual_ru

logging.info('Calibrate current electrification')
self.df[SET_ELEC_CURRENT] = 0


# This if function here skims through T&D columns to identify if any non 0 values exist; Then it defines priority accordingly.
if max(self.df[SET_DIST_TO_TRANS]) > 0:
Expand Down
40 changes: 35 additions & 5 deletions onsset/runner.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
# Defines the modules

from onsset import *
import logging
import os

import pandas as pd
from onsset import (SET_ELEC_ORDER, SET_LCOE_GRID, SET_MIN_GRID_DIST,
SET_MV_CONNECT_DIST, SettlementProcessor, Technology)
from onsset.specs import (SPE_COUNTRY, SPE_ELEC, SPE_ELEC_MODELLED,
SPE_ELEC_RURAL, SPE_ELEC_URBAN, SPE_END_YEAR,
SPE_EXISTING_GRID_COST_RATIO,
SPE_GRID_CAPACITY_INVESTMENT, SPE_GRID_LOSSES,
SPE_MAX_GRID_EXTENSION_DIST,
SPE_NUM_PEOPLE_PER_HH_RURAL,
SPE_NUM_PEOPLE_PER_HH_URBAN, SPE_POP, SPE_POP_FUTURE,
SPE_START_YEAR, SPE_URBAN, SPE_URBAN_FUTURE,
SPE_URBAN_MODELLED)
from openpyxl import load_workbook

def calibration(specs_path, csv_path, specs_path_calib, calibrated_csv_path):


specs = pd.read_excel(specs_path, index_col=0)
def calibration(specs_path, csv_path, specs_path_calib, calibrated_csv_path):
"""
Arguments
---------
specs_path
csv_path
specs_path_calib
calibrated_csv_path
"""
SpecsData = pd.read_excel(specs_path, sheet_name='SpecsData')
settlements_in_csv = csv_path
settlements_out_csv = calibrated_csv_path
Expand Down Expand Up @@ -54,7 +74,7 @@ def calibration(specs_path, csv_path, specs_path_calib, calibrated_csv_path):

# In case there are limitations in the way grid expansion is moving in a country, this can be reflected through gridspeed.
# In this case the parameter is set to a very high value therefore is not taken into account.


SpecsData.loc[0, SPE_URBAN_MODELLED] = urban_modelled
SpecsData.loc[0, SPE_ELEC_MODELLED] = elec_modelled
Expand All @@ -73,6 +93,16 @@ def calibration(specs_path, csv_path, specs_path_calib, calibrated_csv_path):
onsseter.df.to_csv(settlements_out_csv, index=False)

def scenario(specs_path, calibrated_csv_path, results_folder, summary_folder):
"""
Arguments
---------
specs_path : str
calibrated_csv_path : str
results_folder : str
summary_folder : str
"""


ScenarioInfo = pd.read_excel(specs_path, sheet_name='ScenarioInfo')
Expand Down
37 changes: 37 additions & 0 deletions onsset/specs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Columns in the specs file must match these exactly
"""
SPE_COUNTRY = 'Country'
SPE_POP = 'PopStartYear' # The actual population in the base year
SPE_URBAN = 'UrbanRatioStartYear' # The ratio of urban population (range 0 - 1) in base year
SPE_POP_FUTURE = 'PopEndYear'
SPE_URBAN_FUTURE = 'UrbanRatioEndYear'
SPE_URBAN_MODELLED = 'UrbanRatioModelled' # The urban ratio in the model after calibration (for comparison)
SPE_URBAN_CUTOFF = 'UrbanCutOff' # The urban cutoff population calirated by the model, in people per km2
SPE_URBAN_GROWTH = 'UrbanGrowth' # The urban growth rate as a simple multplier (urban pop future / urban pop present)
SPE_RURAL_GROWTH = 'RuralGrowth' # Same as for urban
SPE_NUM_PEOPLE_PER_HH_RURAL = 'NumPeoplePerHHRural'
SPE_NUM_PEOPLE_PER_HH_URBAN = 'NumPeoplePerHHUrban'
SPE_DIESEL_PRICE_LOW = 'DieselPriceLow' # Diesel price in USD/litre
SPE_DIESEL_PRICE_HIGH = 'DieselPriceHigh' # Same, with a high forecast var
SPE_GRID_PRICE = 'GridPrice' # Grid price of electricity in USD/kWh
SPE_GRID_CAPACITY_INVESTMENT = 'GridCapacityInvestmentCost' # grid capacity investments costs from TEMBA USD/kW
SPE_GRID_LOSSES = 'GridLosses' # As a ratio (0 - 1)
SPE_BASE_TO_PEAK = 'BaseToPeak' # As a ratio (0 - 1)
SPE_EXISTING_GRID_COST_RATIO = 'ExistingGridCostRatio'
SPE_MAX_GRID_DIST = 'MaxGridDist'
SPE_ELEC = 'ElecActual' # Actual current percentage electrified population (0 - 1)
SPE_ELEC_MODELLED = 'ElecModelled' # The modelled version after calibration (for comparison)
SPE_ELEC_URBAN = 'Urban_elec_ratio' # Actual electrification for urban areas
SPE_ELEC_RURAL = 'Rural_elec_ratio' # Actual electrification for rural areas
SPE_MIN_NIGHT_LIGHTS = 'MinNightLights'
SPE_MAX_GRID_EXTENSION_DIST = 'MaxGridExtensionDist'
SPE_MAX_ROAD_DIST = 'MaxRoadDist'
SPE_POP_CUTOFF1 = 'PopCutOffRoundOne'
SPE_POP_CUTOFF2 = 'PopCutOffRoundTwo'
SPE_ELEC_LIMIT = "ElecLimit"
SPE_INVEST_LIMIT = "InvestmentLimit"
SPE_DIST_TO_TRANS = "DistToTrans"

SPE_START_YEAR = "StartYear"
SPE_END_YEAR = "EndYEar"
SPE_TIMESTEP = "TimeStep"

0 comments on commit 9e81350

Please sign in to comment.