API Documentation

Model class

class calliope.Model(config_run=None, override=None)[source]

Calliope model.


config_run : str or AttrDict, optional

Path to YAML file with run settings, or AttrDict containing run settings. If not given, the included default run and model settings are used.

override : AttrDict, optional

Provide any additional options or override options from config_run by passing an AttrDict of the form {'model_settings': 'foo.yaml'}. Any option possible in run.yaml can be specified in the dict, inluding override. options.


In instances where a technology is allowing export, e.g. techs.ccgt.export: true then change ‘true’ to the carrier of that technology.


Check if a given functionality of the model is required, based on whether there is any reference to it in model configuration that isn’t defaults.

  • func_name: str; the funcitonality to check

Returns: bool; Whether the functionality is switched is on (True) or off (False)


Generate the model and store it under the property m.

t_start : if self.mode == ‘operate’, this must be specified, but that is done automatically via solve_iterative() when calling run()

Get capacity factor.

NB: Only production, not consumption, is used in calculations.

get_carrier(y, direction, level=None, primary=False, all_carriers=False)[source]

Get the carrier_in or carrier_out of a technology in the model


y: str


direction: str, `in` or `out`

For carrier_in and carrier_out repectively

level: int; 2 or 3; optional, default = None

for conversion_plus technologies, define the carrier level if not top level, e.g. level=3 gives carrier_out_3

primary: bool, optional, default = False

give primary carrier for a given technology, which is a carrier in carrier_out given ass primary carrier in the technology definition

all_carriers: bool, optional, default = False

give all carriers for tech y and given direction. For conversion_plus technologies, this will give an array of carriers, if more than one carrier has been defined in the given direction. All levels are combined.

get_cp_carriers(y, x=None, direction='out')[source]

Find all carriers for conversion_plus technology & return the primary output carrier as string and all other output carriers as list of strings


Where distances are not given for links, use any metadata to fill in the gap. Distance calculated using vincenty inverse formula (given in utils module).

get_eff_ref(var, y, x=None)[source]

Get reference efficiency, falling back to efficiency if no reference efficiency has been set.

get_group_members(group, in_model=True, head_nodes_only=True, expand_transmission=True)[source]

Return the member technologies of a group. If in_model is True, only technologies (head nodes) in use in the current model are returned.

  • A list of group members if there are any.
  • If a group has no members (is only member of other groups, i.e. a head node), a list with a single item containing only the group/technology itself.
  • An empty list if the group is defined but not allowed in the current model.
  • None if the group doesn’t exist.

Other arguments:

head_nodes_only : if True, don’t return intermediate
groups, i.e. technology definitions that are inherited from. Setting this to False only makes sense if in_model is also False, because in_model=True implies that only head nodes are returned.
expand_transmission : if True, return in-model
transmission technologies in the form tech:location.

Get levelized costs.

NB: Only production, not consumption, is used in calculations.

get_option(option, x=None, default=None, ignore_inheritance=False)[source]

Retrieves options from model settings for the given tech, falling back to the default if the option is not defined for the tech.

If x is given, will attempt to use location-specific override from the location matrix first before falling back to model-wide settings.

If default is given, it is used as a fallback if no default value can be found in the regular inheritance chain. If default is None and the regular inheritance chain defines no default, an error is raised.

If ignore_inheritance is True, the default is immediately used instead of a search through the inheritance chain if the option has not been set for the given tech.

If the first segment of the option contains ‘:’, it will be interpreted as implicit tech subsetting: e.g. asking for ‘hvac:r1’ implicitly uses ‘hvac:r1’ with the parent ‘hvac’, even if that has not been defined, to search the option inheritance chain.


  • model.get_option('ccgt.costs.om_var')
  • model.get_option('csp.weight')
  • model.get_option('csp.r', x='33')
  • model.get_option('ccgt.costs.om_var',          default='defaults.costs.om_var')

Returns the abstract base technology from which y descends.

get_t(timestamp, offset=0)[source]

Get a timestamp before/after (by offset) from the given timestamp in the model’s set of timestamps. Raises ModelError if out of bounds.


Returns resolution of data in hours.

If verify=True, verifies that the entire file is at the same resolution. self.get_timeres(verify=True) can be called after Model initialization to verify this.

get_totals(t_subset=None, apply_weights=True)[source]

Get total produced and consumed per technology and location.

get_var(var, dims=None, standardize_coords=True)[source]

Return output for variable var as a pandas.Series (1d), pandas.Dataframe (2d), or xarray.DataArray (3d and higher).


var : variable name as string, e.g. ‘es_prod’

dims : list, optional

indices as strings, e.g. (‘y’, ‘x’, ‘t’); if not given, they are auto-detected


Find any constraints/costs values requested as from ‘file’ in YAMLs and store that information.

ischild(y, of)[source]

Returns True if y is a child of of, else False


Load results into model instance for access via model variables.


Return the timestep prior to the given timestep.


Called from both load_solution() and load_solution_iterative()


Populate parameter data from CSV files or model configuration.


Instantiate and solve the model


Save model solution. how can be ‘netcdf’ or ‘csv’

scale_to_peak(df, peak, scale_time_res=True)[source]

Returns the given dataframe scaled to the given peak value.

If scale_time_res is True, the peak is multiplied by the model’s time resolution. Set it to False to scale things like efficiencies.

set_option(option, value, x=None)[source]

Set option to value. Returns None on success.

A default can be set by passing an option like defaults.constraints.e_eff.

warmstart : (default False) re-solve an updated model

Returns: None


Solve iterative by updating model parameters.

By default, on optimizations subsequent to the first one, warmstart is used to speed up the model generation process.

Returns None on success, storing results under self.solution



Minimizes total system monetary cost. Used as a default if a model does not specify another objective.


Defines variables:

  • r: resource -> tech (+ production
  • r_area: resource collector area
  • r2: secondary resource -> storage (+ production)
  • c_prod: tech -> carrier (+ production)
  • c_con: tech <- carrier (- consumption)
  • s_cap: installed storage capacity
  • r_cap: installed resource <-> storage conversion capacity
  • e_cap: installed storage <-> grid conversion capacity (gross)
  • r2_cap: installed secondary resource conversion capacity
  • cost: total costs
  • cost_con: construction costs
  • cost_op_fixed: fixed operation costs
  • cost_op_var: variable operation costs
  • cost_op_fuel: primary resource fuel costs
  • cost_op_r2: secondary resource fuel costs
calliope.constraints.base.get_constraint_param(model, param_string, y, x, t)[source]

Function to get values for constraints which can optionally be loaded from file (so may have time dependency).

model = calliope model param_string = constraint as string y = technology x = location t = timestep

calliope.constraints.base.get_cost_param(model, param_string, k, y, x, t)[source]

Function to get values for constraints which can optionally be loaded from file (so may have time dependency).

model = calliope model cost = cost name, e.g. ‘om_fuel’ k = cost type, e.g. ‘monetary’ y = technology x = location t = timestep


Constrain e_cap symmetrically for transmission nodes. Transmission techs only.


Constrain groups of technologies to reach given fractions of e_prod.


r_area of all technologies requiring physical space cannot exceed the available area of a location. Available area defined for parent locations (in which there are locations defined as being ‘within’ it) will set the available area limit for the sum of all the family (parent + all desecendants).

To define, assign a value to available_area for a given location, e.g.:

        techs: ['csp']
        available_area: 100000

To avoid including descendants in area limitation, ignore_descendants can be specified for the location, in the same way as available_area.


Ramping rate constraints.

Depends on: node_energy_balance, node_constraints_build

Time series

calliope.time_funcs.apply_clustering(data, timesteps, clustering_func, how, normalize=True, **kwargs)[source]

Apply the given clustering function to the given data.


data : xarray.Dataset

timesteps : pandas.DatetimeIndex or list of timesteps or None

clustering_func : str

Name of clustering function.

how : str

How to map clusters to data. ‘mean’ or ‘closest’.

normalize : bool, optional

If True (default), data is normalized before clustering is applied, using normalized_copy().

**kwargs : optional

Arguments passed to clustering_func.


data_new_scaled : xarray.Dataset

calliope.time_funcs.drop(data, timesteps, padding=None)[source]

Drop timesteps from data, with optional padding around into the contiguous areas encompassed by the timesteps.


Return a copy of data, with the absolute taken and normalized to 0-1.

The maximum across all regions and timesteps is used to normalize.

calliope.time_masks.extreme(data, tech, var='r', how='max', length='1D', n=1, groupby_length=None, locations=None, padding=None)[source]

Returns timesteps for period of length where var for the technology tech across the given list of locations is either minmal or maximal.


data : xarray.Dataset

tech : str

Technology whose var to find extreme for.

var : str, optional

default ‘r’

how : str, optional

‘max’ (default) or ‘min’.

length : str, optional

Defaults to ‘1D’.

n : int, optional

Number of periods of length to look for, default is 1.

groupby_length : str, optional

Group time series and return n periods of length for each group.

locations : list, optional

List of locations to use, if None, uses all available locations.

padding : int, optional

Pad beginning and end of the unmasked area by the number of timesteps given.

normalize : bool, optional

If True (default), data is normalized using normalized_copy().

calliope.time_masks.zero(data, tech, var='r', locations=None)[source]

Returns timesteps where var for the technology tech across the given list of locations is zero.

If locations not given, uses all available locations.

calliope.time_clustering.cophenetic_corr(X, Z)[source]

Get the Cophenetic Correlation Coefficient of a clustering with help of the cophenet() function. This (very very briefly) compares (correlates) the actual pairwise distances of all your samples to those implied by the hierarchical clustering. The closer the value is to 1, the better the clustering preserves the original distances.

Source: https://joernhees.de/blog/2015/08/26/scipy-hierarchical-clustering-and-dendrogram-tutorial/

calliope.time_clustering.fancy_dendrogram(*args, **kwargs)[source]

Code adapted from: https://joernhees.de/blog/2015/08/26/scipy-hierarchical-clustering-and-dendrogram-tutorial/

calliope.time_clustering.get_clusters_hierarchical(data, tech=None, max_d=None, k=None)[source]

data : xarray.Dataset

Should be normalized

max_d : float or int, optional

Max distance for returning clusters.

k : int, optional

Number of desired clusters.





calliope.time_clustering.get_clusters_kmeans(data, tech=None, timesteps=None, k=5)[source]

data : xarray.Dataset

Should be normalized


clusters : dataframe

Indexed by timesteps and with locations as columns, giving cluster membership for first timestep of each day.


calliope.time_clustering.map_clusters_to_data(data, clusters, how)[source]

Returns a copy of data that has been clustered.


how : str

How to select data from clusters. Can be mean (centroid) or closest.

Reading results


Combines output files from directory and return an AttrDict containing them all.

If a solution is missing or there is an error reading it, an empty AttrDict is added to the results in its stead and the error is logged.


Read model solution from NetCDF4 file

Analyzing results

calliope.analysis.areas_below_resolution(solution, resolution)[source]

Returns a list of (start, end) timestamp tuples delimiting those areas in the solution below the given timestep resolution (in hours).

calliope.analysis.get_delivered_cost(solution, cost_class='monetary', carrier='power', count_unmet_demand=False)[source]

Get the levelized cost per unit of energy delivered for the given cost_class and carrier.


solution : solution container

cost_class : str, default ‘monetary’

carrier : str, default ‘power’

count_unmet_demand : bool, default False

Whether to count the cost of unmet demand in the final delivered cost.


Assuming that solution specifies a domestic cost class to give each technology a domesticity score, return the total domestic supply index for the given solution.

calliope.analysis.get_group_share(solution, techs, group, var='e_prod')[source]

From solution.summary, get the share of the given list of techs from the total for the given group, for the given var.

calliope.analysis.get_hhi(solution, shares_var='e_cap', exclude_patterns=['unmet_demand'])[source]

Returns the Herfindahl-Hirschmann diversity index.

\(HHI = \sum_{i=1}^{I} p_{i}^2\)

where \(p_{i}\) is the percentage share of each technology i (0-100).

\(HHI\) ranges between 0 and 10,000. A value above 1800 is considered a sign of a concentrated market.

calliope.analysis.get_levelized_cost(solution, cost_class='monetary', carrier='power', groups=None, locations=None, unit_multiplier=1.0)[source]

Get the levelized cost per unit of energy produced for the given cost_class and carrier, optionally for a subset of technologies given by groups and a subset of locations.


solution : solution container

cost_class : str, default ‘monetary’

carrier : str, default ‘power’

groups : list, default None

Limit the computation to members of the given groups (see the groups table in the solution for valid groups). Defaults to [‘supply’, ‘supply_plus’] if not given.

locations : str or iterable, default None

Limit the computation to the given location or locations.

unit_multiplier : float or int, default 1.0

Adjust unit of the returned cost value. For example, if model units are kW and kWh, unit_multiplier=1.0 will return cost per kWh, and unit_multiplier=0.001 will return cost per MWh.

calliope.analysis.get_swi(solution, shares_var='e_cap', exclude_patterns=['unmet_demand'])[source]

Returns the Shannon-Wiener diversity index.

\(SWI = -1 \times \sum_{i=1}^{I} p_{i} \times \ln(p_{i})\)

where where I is the number of categories and \(p_{i}\) is each category’s share of the total (between 0 and 1).

\(SWI\) is zero when there is perfect concentration.

calliope.analysis.get_unmet_demand_hours(solution, carrier='power', details=False)[source]

Get information about unmet demand from solution.


solution : solution container

carrier : str, default ‘power’

details : bool, default False

By default, only the number of hours with unmet are returned. If details is True, a dict with ‘hours’, ‘timesteps’, and ‘dates’ keys is returned instead.

calliope.analysis.map_results(results, func, as_frame=False)[source]

Applies func to each model solution in results, returning a pandas DataFrame (if as_frame is True) or Series, indexed by the run names (if available).

calliope.analysis.plot_carrier_production(solution, carrier='power', subset={}, **kwargs)[source]

Generate a stackplot of the production by the given carrier.


solution : model solution xarray.Dataset

carrier : str, optional

Name of the carrier to plot, default ‘power’.

subset : dict, optional

Specify an additional subset of Dataset coordinates, for example, dict(t=slice(‘2005-02-01’, ‘2005-02-10’).

**kwargs : optional

Passed to plot_timeseries.

calliope.analysis.plot_installed_capacities(solution, tech_types=['supply', 'supply_plus', 'conversion', 'conversion_plus', 'storage'], unit_multiplier=1.0, unit_label='kW', **kwargs)[source]

Plot installed capacities (e_cap) with a bar plot.


solution : model solution xarray.Dataset

tech_types : list, optional

Technology types to include in the plot. Default is [‘supply’, ‘supply_plus’, ‘conversion’, ‘conversion_plus’, ‘storage’]

unit_multiplier : float or int, optional

Multiply installed capacities by this value for plotting. Defaults to 1.0

unit_label : str, optional

Label for capacity values. Default is ‘kW’, adjust this when changing unit_multiplier.

**kwargs : optional

are passed to pandas.DataFrame.plot()

calliope.analysis.plot_timeseries(solution, data, carrier='power', demand='demand_power', tech_types=['supply', 'supply_plus', 'conversion', 'conversion_plus', 'storage', 'unmet_demand'], colormap=None, ticks=None, resample_options=None, resample_func=None, add_legend=True, ax=None)[source]

Generate a stackplot of data for the given carrier, plotting demand on top.

Use plot_carrier_production for a simpler way to plot production by a given carrier.


solution : model solution xarray.Dataset

data : xarray.Dataset

Subset of solution to plot.

carrier : str, optional

Name of the carrier to plot, default ‘power’.

demand : str, optional

Name of a demand tech whose time series to plot on top, default ‘demand_power’.

tech_types : list, optional

Technology types to include in the plot. Default list is [‘supply’, ‘supply_plus’ , ‘conversion’, ‘storage’, ‘unmet_demand’].

colormap : matplotlib colormap, optional

Colormap to use. If not given, the colors specified for each technology in the solution’s metadata are used.

ticks : str, optional

Where to draw x-axis (time axis) ticks. By default (None), auto-detects, but can manually set to either ‘hourly’, ‘daily’, or ‘monthly’.

resample_options : dict, optional

Give options for pandas.DataFrame.resample in a dict, to resample the entire time series prior to plotting. Both resample_options and resample_func must be given for resampling to happen. Default None.

resample_func : string, optional

Give the name of the aggregating function to use when resampling, e.g. “mean” or “sum”. Default None.

calliope.analysis.plot_transmission(solution, tech='ac_transmission', carrier='power', labels='utilization', figsize=(15, 15), fontsize=9, show_scale=True, ax=None, **kwargs)[source]

Plot transmission links on a map. Requires that model metadata have been defined with a lat/lon for each model location and a boundary for the map display.

Requires Basemap and NetworkX to be installed.


solution : solution container

tech : str, default ‘ac_transmission’

Which transmission technology to plot.

carrier : str, default ‘power’

Which carrier to plot transmission for.

labels : str, default ‘utilization’

Determines how transmission links are labeled, either transmission or utilization.

figsize : (int, int), default (15, 15)

Size of resulting figure.

fontsize : int, default 9

Font size of figure labels.

show_scale : bool, default True

Plot a distance scale on the map.

ax : matplotlib axes, default None

**kwargs : are passed to analysis_utils.plot_graph_on_map()

Utility classes: AttrDict, Parallelizer, Exceptions

class calliope.utils.AttrDict(source_dict=None)[source]

A subclass of dict with key access by attributes:

d = AttrDict({'a': 1, 'b': 2})
d.a == 1  # True

Includes a range of additional methods to read and write to YAML, and to deal with nested keys.


Return the AttrDict as a pure dict (with nested dicts if necessary).


Override copy method so that it returns an AttrDict


Delete the given key. Properly deals with nested keys.

classmethod from_yaml(f, resolve_imports=True)[source]

Returns an AttrDict initialized from the given path or file object f, which must point to a YAML file.

If resolve_imports is True, import: statements are resolved recursively, else they are treated like any other key.

When resolving import statements, anything defined locally overrides definitions in the imported file.

classmethod from_yaml_string(string)[source]

Returns an AttrDict initialized from the given string, which must be valid YAML.

get_key(key, default=MISSING)[source]

Looks up the given key. Like set_key(), deals with nested keys.

If default is anything but _MISSING, the given default is returned if the key does not exist.


Initialize a new AttrDict from the given dict. Handles any nested dicts by turning them into AttrDicts too:

d = AttrDict({'a': 1, 'b': {'x': 1, 'y': 2}})
d.b.x == 1  # True

Returns all keys in the AttrDict, sorted, including the keys of nested subdicts (which may be either regular dicts or AttrDicts).

If subkeys_as='list' (default), then a list of all keys is returned, in the form ['a', 'b.b1', 'b.b2'].

If subkeys_as='dict', a list containing keys and dicts of subkeys is returned, in the form ['a', {'b': ['b1', 'b2']}].

set_key(key, value)[source]

Set the given key to the given value. Handles nested keys, e.g.:

d = AttrDict()
d.set_key('foo.bar', 1)
d.foo.bar == 1  # True
to_yaml(path=None, convert_objects=True, **kwargs)[source]

Saves the AttrDict to the given path as a YAML file.

If path is None, returns the YAML string instead.

Any additional keyword arguments are passed to the YAML writer, so can use e.g. indent=4 to override the default of 2.

convert_objects (defaults to True) controls whether Numpy objects should be converted to regular Python objects, so that they are properly displayed in the resulting YAML output.

union(other, allow_override=False, allow_replacement=False)[source]

Merges the AttrDict in-place with the passed other AttrDict. Keys in other take precedence, and nested keys are properly handled.

If allow_override is False, a KeyError is raised if other tries to redefine an already defined key.

If allow_replacement, allow “_REPLACE_” key to replace an entire sub-dict.

class calliope.Parallelizer(target_dir, config_run=None)[source]


  • target_dir: path to output directory for parallel runs.
  • config_run: path to YAML file with run settings. If not given, the included example run.yaml is used.
exception calliope.exceptions.ModelError[source]

ModelErrors should stop execution of the model, e.g. due to a problem with the model formulation or input data.

exception calliope.exceptions.ModelWarning[source]

ModelWarnings should be raised for possible model errors, but where execution can still continue.

Previous: Development guide | Next: Index