API Reference


openelec.conv module

Module for loading and saving.


  • read_data
  • merge_geometry
  • spatialise
  • geojsonify
  • geometry
  • properties
  • overpass
  • json2geojson


openelec.conv.geojsonify(gdf, property_cols=[])[source]

Convert GeoDataFrame to GeoJSON that can be supplied to JavaScript.

  • gdf (geopandas.GeoDataFrame) – GeoDataFrame to be converted.
  • property_cols (list, optional) – List of column names from gdf to be included in ‘properties’ of each GeoJSON feature.

geoJson – A GeoJSON representatial List of column names from gdf to be included in ‘properties’ of each GeoJSON feature.

Return type:



geojson – A GeoJSON representation that can be parsed by standard JSON readers.

Return type:



Convert a GeoDataFrame geometry value into a GeoJSON-friendly form..

Parameters:coords (shapely.LineString, shapely.Polygon or shapely.MultiPolygon) – A single geometry entry from a GeoDataFrame.
Returns:geom_dict – A GeoJSON geometry element of the form ‘geometry’: {
’type’: type, ‘coordinates’: coords


Return type:dict

Convert a json from OSM Overpass to a GeoJSON.

Parameters:items (json) – The JSON representation.
Returns:geojson – As a GeoJSON.
Return type:dict
openelec.conv.merge_geometry(results, geometry, columns=None)[source]

Merge results from modelling with an original input geometry, using the index as key for both.

  • results (list of dicts) – Output from modelling.
  • geometry (GeoDataFrame) – Target geometry with amtching index.
  • columns (list, optional) – List of columns to include in output. If not provided, keep all.

spatial – Results with geometry.

Return type:



Get OSM Overpass results from specified bounds as GeoJSON.

Parameters:bounds (str) – String in this format: “S, W, N, E”
Returns:geojson – GeoJSON results.
Return type:dict
openelec.conv.properties(row, property_cols)[source]

Get the selected columns from the pandas row as a GeoJSON-friendly dict.

  • row (pandas.Series) – A single row from a GeoDataFrame.
  • property_cols (list) – List of column names to be added.

prop_dict – A GeoJSON element of the form properties: {

’column1’: property1, ‘column2’: property2, …


Return type:



Read targets (clusters, buildings) data from a file or other source.

Parameters:data (Path, str, dict) – Path to a Fiona-readable file, or GeoJSON-like dict. Can also be a string representation of a GeoJSON.
Returns:targets – The data filtered and processed.
Return type:GeoDataFrame
openelec.conv.save_to_path(path, **features)[source]

Save the provided features in the directory specified. File names are taken from the keywords.

openelec.conv.spatialise(results, type='line')[source]

Convert results to a GeoDataFrame using values to create a geometry.

  • results (list of dicts) – An output from the modelling.
  • type (str, optional (default 'line'.)) – What type of geometry it is. (Currently only implemented for ‘line’).

spatial – Results with geometry.

Return type:


openelec.local module

local module for openelec Tool designed to take a small village and estimate the optimum connections, based on a PV installation location and economic data.

Includes LocalModel class and calculate_profit function.

class openelec.local.LocalModel(data)[source]

Bases: openelec.model.Model

Inherits from Model. Goal is to fully merge NationalModel and LocalModel, as they share lots of functionality.

This class provides most of the functionality for using openelec at the local level.


Filter on population and assign whether currently electrified.

  • targets (GeoDataFrame) – Loaded targets.
  • min_area (int, optional (default 20.)) – Minimum target area in m2.

Create an MST connecting the target features.

Parameters:origin (tuple of two floats) – Tuple of format (latitude, longitude) of origin point (such as a generator) if desired. If not supplied, the largest target building is used instead,

Run the model with the given economic parameters and return the processed network and nodes.

cut arcs one by one, see which cut is the most profitable, and then take that network and repeat the process annual income should be specified by the nodes

Then we start with the complete network, and try ‘deleting’ each arc. Whichever deletion is the most profitable, we make it permanent and repeat the process with the new configuration. This continues until there are no more increases in profitability to be had.

Parameters:target_coverage (float, optional) – If provided, model will aim to achieve this level of population coverage, rather than optimising on NPV.
parameters(demand, tariff, gen_cost, cost_wire, cost_connection, opex_ratio, years, discount_rate)[source]

Set up model parameters.

  • demand (int) – Demand in kWh/person/month.
  • tariff (float) – Tariff to be charged in USD/kWh.
  • gen_cost (int) – Generator cost in USD/kW.
  • cost_wire (int) – Wire cost in USD/m.
  • cost_connection (int) – Cost per household connection in USD.
  • opex_ratio (float) – Annual OPEX as a percentage of CAPEX (range 0 -1).
  • years (int) – Project duration in years.
  • discount_rate (float) – Discount rate to be used for NPV calculation (range 0-1).

Convert all model output to GeoDataFrames.


Calculate some quick summary numbers for the village.

Returns:results – Dict of summary results.
Return type:dict
openelec.local.calculate_profit(network, nodes, index, disabled_arc_index, cost, income_per_month, cost_wire, cost_connection, num_people_per_m2, demand, tariff)[source]

Here we recurse through the network and calculate profit, starting with all arcs that connect to the index node, and get the end-nodes for those arcs calculate profit on those nodes, and then recurse! disabled_arc should be treated as if disabled

  • nodes (network,) – Current state of both.
  • index (int) – Current index.
  • disabled_arc_index (int) – Arc that is currently disabled.
  • etc (cost) –

openelec.model module

model module for openelec.

Provides common functionality for LocalModel and NationalModel.

class openelec.model.Model(data)[source]

Bases: object

Base class for NationalModel and LocalModel.

results_as_geojson(network_columns=None, targets_columns=None)[source]

Convert all model output to GeoJSON.


Save the resultant network and buildings to GeoJSON files. spatialise() must have been run before.

Parameters:path (str, Path) – Path to a directory to create GeoJSON files. Will be created if needed, will not prompt on overwrite.
setup(sort_by=None, **kwargs)[source]

Basic set up on target features.

  • min_area (int, optional (default 20.)) – Area in m2, below which features will be excluded.
  • **kwargs (**dict) – see baseline()

openelec.national module

national module for openelec

Includes NationalModel class and find_best function.

class openelec.national.NationalModel(data)[source]

Bases: openelec.model.Model

Inherits from Model. Goal is to fully merge NationalModel and LocalModel, as they share lots of functionality.

This class provides most of the functionality for using openelec at the national level.


Filter on population and assign whether currently electrified.


Create an MST connecting the target features.


Calculate demand level in kWh/p/month, either from MTF or using a simple formula.

# TODO Add productive use, schools

dynamic(steps=4, years_per_step=5)[source]

Run the model dynamically, splitting into a specified number of steps with a number of years between each one. Creates an iterator that yields results after each step.

  • steps (int, optional (default 4.)) – Number of steps to use.
  • years_per_step (int, optional (default 5.)) – Number of years per step.
  • demand_factor (int, optional (default None.)) – If provided, uses this factor in demand calculations. If None, uses the MTF levels instead.
  • targets_out, networks_out (GeoDataFrames) – The next step of targets and network.
  • results (dict) – The next step of results.

Run the dyamic model and combine the results into a single set of GeoDataFrames and a results dict.

  • targets, network (GeoDataFrames) – Combined targets and network.
  • results (dict) – Dict of results keyed on step number.

Calibrate initial electricity access levels (per electrified cluster) to match national statistics.


Run the national planning model with the provided parameters.

Then we’re ready to calculate the optimum grid extension. This is done by expanding out from each already connected node, finding the optimum connection of nearby nodes. This is then compared to the off-grid cost and if better, these nodes are marked as connected. Then the loop continues until no new connections are found.

parameters(grid_mv_cost=50, grid_lv_cost=3, grid_trans_cost=3500, grid_conn_cost=200, grid_opex_ratio=0.02, mg_gen_cost=4000, mg_lv_cost=2, mg_conn_cost=100, mg_opex_ratio=0.02, actual_pop=10000000.0, pop_growth=0.01, access_tot=0.3, access_urban=0.66, grid_dist_connected=2, minimum_pop=100, gdp_growth=0.02, discount_rate=0.08, people_per_hh=5, target_access=1.0, demand_factor=5, use_mtf=False)[source]

Set up model parameters


Basic filtering and processing on results. Targets ‘type’ can be one of: - densify: was always connected - grid: new grid connection - offgrid: new off-grid connection TODO Add no-connection type.

Parameters:targets (network,) – Output from model.

Calculate some summary results.

Returns:results – Dict of summary results.
Return type:dict
openelec.national.find_best(network, nodes, index, prev_arc, b_demand=0, b_length=1e-09, b_nodes=[], b_arcs=[], c_demand=0, c_length=1e-09, c_nodes=[], c_arcs=[])[source]

This function recurses the network, bringing current c_ values with it. These aren’t returned, so are left untouched side-branch explorations. The b_ values are returned, and updated when a better configuration found. Thus these will remember the best solution including all side meanders.

openelec.network module

network module of openelec. Provides functionality for creating MST and network from input points.


  • create_network
  • spanning_tree
  • add_origin
  • remove_existing
  • direct_network
openelec.network.add_origin(points, origin)[source]

If origin not specified, the model defaults to using index 0 as the ‘main’ point. Thus targets should already have been sorted by population/area with largest first.

openelec.network.create_network(targets, columns, existing_network=False, directed=False, origin=None)[source]

We then take all the clusters and calculate the optimum network that connects them all together. We use this to create a graph network of and nodes and arcs representing the clusters and connections.

  • clusters (GeoDataFrame) – The prepared clusters.
  • columns (list) – List of columns to include.
  • existing_network (boolean, optional (default False.)) – Whether there is an existing network. In this case, redundant lines in new network are removed.
  • directed (boolean, optional (default False.)) – Whether the output network should be directed.
  • origin (tuple, optional) – Location of an origin (e.g. generator) for the network. Should be of the form (latitude, longitude) in WGS84 coordinates. If not provided, the first element is set as origin.

  • network (list of dicts) – The network arcs.
  • nodes (list of dicts) – The network nodes.

openelec.network.direct_network(network, nodes, index, prev)[source]

Recursive function to direct the network from the PV point outwards We need to calculate the directionality of the network, starting from the PV location and reaching outwards to the furthest branches.

We use this to calculate, for each node, it’s marginal and total distance from the PV location. At the same time, we tell each arc which node is ‘upstream’ of it, and which is ‘downstream’. We also tell each node which arcs (at least one, up to three or four?) it is connected to.

  • network (list of dicts) – Containing the arc representations.
  • nodes (list of dicts) – Containing the building node representations.
  • index (int) – Current node index that we’re looking at.

  • network (list of lists) – Nearby network directed for current node.
  • nodes (list of list) – The nodes object.

openelec.network.remove_existing(network, nodes)[source]

Set which arcs don’t already exist (and the remainder do!)

openelec.network.spanning_tree(X, approximate=False)[source]

Function to calculate the Minimum spanning tree connecting the provided points X. Modified from astroML code in mst_clustering.py

Parameters:X (array_like) – 2D array of shape (n_sample, 2) containing the x- and y-coordinates of the points.
Returns:x_coords, y_coords – the x and y coordinates for plotting the graph. They are of size [2, n_links], and can be visualized using plt.plot(x_coords, y_coords, '-k')
Return type:ndarrays

openelec.prioritise module

prioritising module for openelec


  • priority
openelec.prioritise.priority(clusters, pop_range=None, grid_range=None, ntl_range=None, gdp_range=None, travel_range=None)[source]

Calculate the priority clusters that meet the criteria, and calculate a score from 1-5 for each.

  • clusters (GeoDataFrame) – Village clusters object.
  • min_grid_dist (int) – Minimum distance from grid in metres to consider for clusters.
  • max_ntl (int) – Maximum value of NTL (night time lights) to consider. Range 0-255.

  • clusters (GeoDatFrame) – Processed clusters.
  • summary (dict) – Summary results.

openelec.util module

Helper functions for models.


  • connect_houses
  • stranded_arcs
  • calc_coverage
  • assign_coverage
  • calc_lv
openelec.util.assign_coverage(targets, access_rate)[source]

Estimate level of electricity access for each target.

openelec.util.calc_coverage(weight, pop, conn, pop_tot, target_access, accuracy=0.01, increment=0.1, max_coverage=0.8)[source]

Estimate coverage levels for the given parameters.

  • pop, conn (weight,) – Each a column from targets.
  • pop_tot (int) – Total population.
  • target_access (float) – Target access rate.
  • accuracy (float, optional (default 0.01.)) – Acceptable accuracy level.
  • increment (float, optional (default 0.1.)) – How much to increment each target’s coverage level on each loop.
  • max_coverage (float, optional (default 0.8.)) – Max coverage level for any target.

coverage – Array of coverage levels of same shape as weight.

Return type:

numpy array

openelec.util.calc_lv(people, demand, people_per_hh, area)[source]

Calculate LV cost parameters for the given parameters. Everything is in m and m2.

openelec.util.connect_houses(network, nodes, index)[source]

Then we disconnect all the houses that are no longer served by active arcs, and prune any stranded arcs that remained on un-connected paths. now we need to tell the houses that aren’t connected, that they aren’t connected (or vice-versa)

Start from base, follow connection (similar to calculate_profit) and swith node[6] to 1 wherever connected and only follow the paths of connected houses.

openelec.util.stranded_arcs(network, nodes)[source]

And do the same for the stranded arcs

Module contents

openelec package contains the following modules:

  • model
  • local
  • national
  • io
  • network
  • prioritise
  • util

GPL-3.0 (c) Chris arderne