def _marker(locs_coordinates, location, carrier, tech, prod, scale_factor, techs_colors, is_initial_timestep, add_legend, name): # Example: "Region1: 3552.65 of pipe_import (gas)" hover_info = "%s: %.2f of %s (%s)" % \ (location, prod, tech, carrier) marker_dict = dict( visible=False, hoverinfo="text", text=hover_info, mode="markers", marker=dict( symbol="circle-dot", opacity=0.6, size=prod * scale_factor + 1, color=techs_colors[tech], ), legendgroup=tech, showlegend=False ) marker_legend = dict( visible=False, hoverinfo="text", text=hover_info, mode="markers", marker=dict( symbol="circle-dot", opacity=0.6, size=10, color=techs_colors[tech], ), legendgroup=tech, name=break_name(name, 18) ) if set(locs_coordinates.index) == set(["x", "y"]): h_coord, v_coord = "x", "y" elif set(locs_coordinates.index) == set(["lon", "lat"]): h_coord, v_coord = "lon", "lat" marker_dict[h_coord] = [locs_coordinates[location][h_coord]] marker_dict[v_coord] = [locs_coordinates[location][v_coord]] marker_legend[h_coord] = [None] marker_legend[v_coord] = [None] if is_initial_timestep: # plot only the first timestep data when the chart is initialized marker_dict["visible"] = True marker_legend["visible"] = True if add_legend: return [marker_dict, marker_legend] else: return [marker_dict]
def _get_var_data(cap, model, dataset, visible, subset, sum_dims, squeeze, locations, orientation): if 'systemwide' in cap: array_cap = subset_sum_squeeze(dataset[cap], subset) if 'costs' in array_cap.dims and len(array_cap['costs']) == 1: array_cap = array_cap.squeeze('costs') elif 'costs' in array_cap.dims and len(array_cap['costs']) > 1: raise ValueError( 'Cannot plot {} without subsetting to pick one cost type ' 'of interest'.format(cap)) if 'carriers' not in subset.keys(): array_cap = array_cap.sortby('carriers') else: array_cap = model.get_formatted_array(cap).reindex(locs=locations) array_cap = subset_sum_squeeze(array_cap, subset, sum_dims, squeeze) if len(array_cap.dims) > 2: raise ValueError( 'Maximum two dimensions allowed for plotting capacity, but {} ' 'given as dimensions for {}'.format(array_cap.dims, cap)) if 'techs' not in array_cap.dims: raise ValueError('Cannot plot capacity without `techs` in dimensions') elif 'techs' not in subset.keys(): array_cap = array_cap.sortby('techs') data = [] for tech in array_cap.techs.values: if tech not in dataset.techs.values: continue if 'techs_transmission' in dataset and tech in dataset.techs_transmission.values: continue else: base_tech = dataset.inheritance.loc[{ 'techs': tech }].item().split('.')[0] if base_tech in 'demand': continue if array_cap.loc[{'techs': tech}].sum() > 0: x = array_cap.loc[{'techs': tech}].values name = break_name( model._model_data.names.loc[{ 'techs': tech }].item(), 30) if 'systemwide' in cap: y = natsorted(array_cap.carriers.values) else: if 'locs' in array_cap.dims: y = natsorted(array_cap.locs.values) else: # Single location y = [array_cap.locs.values] if orientation == 'v': x, y = y, x # Flip axes hoverinfo = 'y+name' else: hoverinfo = 'x+name' x, y = x[:: -1], y[:: -1] # Make sure that sorting is from bottom down data.append( go.Bar(x=x, y=y, visible=visible, name=name, legendgroup=tech, text=tech, hoverinfo=hoverinfo, marker=dict( color=model._model_data.colors.loc[{ 'techs': tech }].item()), orientation=orientation)) return data
def _get_var_data(var, model, dataset, visible, subset, sum_dims, squeeze): """ Get variable data from model_data and use it to populate a list with Plotly plots """ carriers = list(dataset.carriers.values) # list to populate data = [] # Clustered data does not get plotted on a datetime axis if 'clusters' in dataset.dims: clusters = dataset.timestep_cluster.to_pandas() cluster_groups = clusters.groupby(clusters).groups # Add an extra timestep at the end of each cluster, so we can break # scatter lines with a NaN between each cluster dummy_timestep = lambda x: pd.to_datetime(x[-1] + pd.Timedelta(100, unit='ns')) reindexing_timesteps = np.concatenate([ group_timesteps.append(pd.Index([dummy_timestep(group_timesteps)])).values for group_timesteps in cluster_groups.values() ]) timesteps = pd.Index(reindexing_timesteps).values.astype(str) # replace dummy timestep with NaN timesteps[pd.Index(reindexing_timesteps).nanosecond == 100] = np.nan timesteps = pd.to_datetime(timesteps, errors='ignore') if var == 'storage_inter_cluster': datesteps = pd.to_datetime(model._model_data.datesteps.values) else: timesteps = pd.to_datetime(model._model_data.timesteps.values) def _get_reindexed_array(array, index=['locs', 'techs'], fillna=None): # reindexing data means that DataArrays have the same values in locs and techs reindexer = {k: sorted(dataset[k].values) for k in index} formatted_array = model.get_formatted_array(array) if fillna is not None: return formatted_array.reindex(**reindexer).fillna(fillna) else: return formatted_array.reindex(**reindexer) def _get_y_vals(array, ignore_clustering=False): if 'clusters' in dataset.dims and not ignore_clustering: return array.to_pandas().reindex(reindexing_timesteps).values else: return array.values if hasattr(model, 'results'): array_prod = _get_reindexed_array('carrier_prod', index=['locs', 'techs', 'carriers'], fillna=0) array_con = _get_reindexed_array('carrier_con', index=['locs', 'techs', 'carriers'], fillna=0) if 'resource_con' in dataset.data_vars: resource_con = _get_reindexed_array('resource_con', fillna=0) else: resource_con = 0 # carrier flow is a combination of carrier_prod, carrier_con and # carrier_export for a given energy carrier if var in carriers: array_flow = (array_prod.loc[dict(carriers=var)] + array_con.loc[dict(carriers=var)]) if 'carrier_export' in dataset: export_flow = subset_sum_squeeze( _get_reindexed_array( 'carrier_export', index=['locs', 'techs', 'carriers'], fillna=0 ).loc[dict(carriers=var)], subset, sum_dims, squeeze ) if 'unmet_demand' in dataset: unmet_flow = subset_sum_squeeze( _get_reindexed_array( 'unmet_demand', index=['locs', 'carriers'], fillna=0 ).loc[dict(carriers=var)], subset, sum_dims, squeeze=False ) # array flow for storage tracks stored energy. carrier_flow is # charge/discharge (including resource consumed for supply_plus techs) elif var == 'storage': array_flow = _get_reindexed_array('storage') if 'resource_eff' in dataset.data_vars: resource_eff = _get_reindexed_array('resource_eff', fillna=1) else: resource_eff = 1 charge = subset_sum_squeeze( -array_con.sum('carriers') + resource_con * resource_eff, subset, sum_dims, squeeze=False ) discharge = -subset_sum_squeeze( array_prod.sum('carriers'), subset, sum_dims, squeeze=False ) elif var == 'resource_con': array_flow = resource_con else: array_flow = _get_reindexed_array(var) array_flow = subset_sum_squeeze(array_flow, subset, sum_dims, squeeze) err_details = ' (variable: `{}`, subset: `{}`, sum_dims: `{}`.'.format(var, subset, sum_dims) if 'timesteps' not in array_flow.dims and 'datesteps' not in array_flow.dims: raise ValueError( '`timesteps` not in plotting data, cannot proceed' + err_details ) if len(array_flow.dims) > 2: if 'costs' in array_flow.dims: err_details = err_details + (' Try subsetting to select a cost class, ' "e.g. subset={'costs': ['monetary']}.") raise ValueError( 'Too many dimensions to plot: `{}`'.format(array_flow.dims) + err_details ) # If techs not given as a subset (implying a desire to order manually), # sort techs such that those varying output least are at the bottom of the stack if subset.get('techs', None) or var == 'storage_inter_cluster': sorted_techs = array_flow.techs.values else: sorted_techs = [ array_flow.techs.values[i] for i in array_flow.var(dim='timesteps').argsort() ] # for tech in array_flow.techs.values: for tech in sorted_techs: tech_dict = {'techs': tech} if not array_flow.loc[tech_dict].sum(): continue # We allow transmission tech information to show up in some cases if 'techs_transmission' in dataset and tech in dataset.techs_transmission.values: base_tech = 'transmission' color = dataset.colors.loc[{'techs': tech.split(':')[0]}].item() name = break_name(dataset.names.loc[{'techs': tech.split(':')[0]}].item(), 30) if var in carriers: continue # no transmission in carrier flow else: base_tech = dataset.inheritance.loc[tech_dict].item().split('.')[0] color = dataset.colors.loc[tech_dict].item() name = break_name(dataset.names.loc[tech_dict].item(), 30) if base_tech == 'demand': # Always insert demand at position 0 in the list, to make # sure it appears on top in the legend data.insert(0, go.Scatter( x=timesteps, y=_get_y_vals(-array_flow.loc[tech_dict]), visible=visible, line=dict(color=color), name=name, legendgroup=tech) ) elif var == 'storage': # stored energy as scatter, carrier/resource prod/con as stacked bar data.insert(0, go.Scatter( x=timesteps, y=_get_y_vals(array_flow.loc[tech_dict]), visible=visible, line=dict(color=color), mode='lines', name=name + ' stored energy', showlegend=False, text=tech + ' stored energy', hoverinfo='x+y+text', legendgroup=tech) ) data.append(go.Bar( x=timesteps, y=_get_y_vals(charge.loc[tech_dict]), visible=visible, name=name, marker=dict(color=color), legendgroup=tech, text=tech + ' charge', hoverinfo='x+y+text' )) data.append(go.Bar( x=timesteps, y=_get_y_vals(discharge.loc[tech_dict]), visible=visible, name=name, marker=dict(color=color, opacity=0.8), legendgroup=tech, text=tech + ' discharge', hoverinfo='x+y+text', showlegend=False )) elif var == 'storage_inter_cluster': data.append(go.Scatter( x=datesteps, y=_get_y_vals(array_flow.loc[tech_dict], ignore_clustering=True), visible=visible, line=dict(color=color), mode='lines', name=name, showlegend=False, text=tech, hoverinfo='x+y+text', legendgroup=tech )) else: data.append(go.Bar( x=timesteps, y=_get_y_vals(array_flow.loc[tech_dict]), visible=visible, name=name, legendgroup=tech, marker=dict(color=color) )) if var in carriers and 'carrier_export' in dataset and export_flow.loc[tech_dict].sum(): data.append(go.Bar( x=timesteps, y=_get_y_vals(-export_flow.loc[tech_dict]), visible=visible, name=name + ' export', legendgroup=tech, marker=dict(color=hex_to_rgba(color, 0.5)) )) if var in carriers and 'unmet_demand' in dataset: data.append(go.Bar( x=timesteps, y=_get_y_vals(unmet_flow), visible=visible, name='Unmet ' + var + ' demand', legendgroup='unmet_demand', marker=dict(color='grey') )) return data
def plot_transmission(model, mapbox_access_token=None, **kwargs): """ Parameters ---------- mapbox_access_token : str, optional If given and a valid Mapbox API key, a Mapbox map is drawn for lat-lon coordinates, else (by default), a more simple built-in map. """ try: coordinates = model._model_data.loc_coordinates.sortby('locs') except AttributeError: raise ValueError('Model does not define location coordinates ' '- no transmission plotting possible.') colors = model._model_data.colors names = model._model_data.names plot_width = 1000 if hasattr(model, 'results'): energy_cap = _get_data(model, 'energy_cap') carrier_prod = _get_data(model, 'carrier_prod', sum_dims=['timesteps', 'carriers']) carrier_con = _get_data(model, 'carrier_con', sum_dims=['timesteps', 'carriers']) energy_flow = carrier_con.fillna(0) + carrier_prod.fillna(0) else: energy_cap = _get_data(model, 'energy_cap_max') energy_flow = energy_cap.copy() energy_flow.loc[dict()] = 0 if sorted(coordinates.coordinates.values) == ['lat', 'lon']: h_coord, v_coord = ('lat', 'lon') if mapbox_access_token: scatter_type = 'scattermapbox' layout_dict = dict( mapbox=dict(accesstoken=mapbox_access_token, center=_get_centre(coordinates), zoom=_get_zoom(coordinates, plot_width), style='light')) else: def get_range(axis): _range = [ coordinates.loc[dict(coordinates=axis)].min().item(), coordinates.loc[dict(coordinates=axis)].max().item() ] _offset = abs(_range[1] - _range[0]) * 0.1 return [_range[0] - _offset, _range[1] + _offset] scatter_type = 'scattergeo' layout_dict = dict(geo=dict( scope='world', projection=dict(type='mercator', scale=1), showland=True, showcountries=True, showsubunits=True, showocean=True, showrivers=True, showlakes=True, lonaxis=dict(range=get_range('lon')), lataxis=dict(range=get_range('lat')), resolution=50, landcolor="rgba(240, 240, 240, 0.8)", oceancolor='#aec6cf', subunitcolor="blue", countrycolor="green", countrywidth=0.5, subunitwidth=0.5, )) else: h_coord, v_coord = ('x', 'y') scatter_type = 'scatter' layout_dict = dict() mid_edge_scatter_dict = { 'type': scatter_type, 'showlegend': False, 'mode': 'markers', 'hoverinfo': 'text', 'opacity': 0 } edge_scatter_dict = { 'type': scatter_type, 'mode': 'lines', 'hoverinfo': 'none', 'opacity': 0.8 } data = [] for tech in sorted(energy_cap.techs.values): per_tech_mid_edge_dict = mid_edge_scatter_dict.copy() per_tech_mid_edge_dict = { **mid_edge_scatter_dict, **{ h_coord: _fill_scatter(coordinates, energy_cap, 'mid_edge', h_coord, tech), v_coord: _fill_scatter(coordinates, energy_cap, 'mid_edge', v_coord, tech), 'text': _fill_scatter(coordinates, energy_cap, 'mid_edge', 'text', tech), 'legendgroup': tech, 'marker': { 'color': colors.loc[dict(techs=tech)].item() } } } h_edge = _fill_scatter(coordinates, energy_cap, 'edge', h_coord, tech) v_edge = _fill_scatter(coordinates, energy_cap, 'edge', v_coord, tech) showlegend = True for i in range(len(h_edge)): data.append({ **edge_scatter_dict, **{ h_coord: h_edge[i], v_coord: v_edge[i], 'showlegend': showlegend, 'legendgroup': tech, 'name': break_name(names.loc[dict(techs=tech)].item()), 'line': { 'color': colors.loc[dict(techs=tech)].item() } } }) showlegend = False data.append(per_tech_mid_edge_dict) node_scatter_dict = { h_coord: [ coordinates.loc[dict(locs=loc, coordinates=h_coord)].item() for loc in coordinates.locs ], v_coord: [ coordinates.loc[dict(locs=loc, coordinates=v_coord)].item() for loc in coordinates.locs ], 'text': [loc.item() for loc in coordinates.locs], 'name': 'Locations', 'type': scatter_type, 'legendgroup': 'locations', 'mode': 'markers', 'hoverinfo': 'text', 'marker': { 'symbol': 'square', 'size': 8, 'color': 'grey' } } data.append(node_scatter_dict) layout_dict.update( dict(width=plot_width, title=model._model_data.attrs['model.name'], autosize=True, hovermode='closest', showlegend=True)) if kwargs.get('html_only', False): del layout_dict['title'] del layout_dict['width'] return data, layout_dict
def _line(locs_coordinates, transmission_type, to_location, from_location, carrier, tech, prod, scale_factor, techs_colors, is_initial_timestep, add_legend, name): # e.g. "Region1->Region2: 256.54 by gas_transmission (gas)" hover_info = "%s->%s: %.2f by %s (%s)" % \ (from_location, to_location, prod, transmission_type, carrier) line = dict( visible=False, mode="lines", hoverinfo="text", text="", line=dict( width=prod * scale_factor + 1, color=techs_colors[transmission_type] ), legendgroup=transmission_type, opacity=0.6, showlegend=False ) line_legend = dict( visible=False, mode="lines", hoverinfo="text", text="", line=dict( width=10, color=techs_colors[transmission_type] ), legendgroup=transmission_type, name=break_name(name, 18), opacity=0.6, ) line_info_marker = dict( visible=False, mode="markers", hoverinfo="text", text=hover_info, marker=dict( symbol="square", opacity=0, color=techs_colors[transmission_type] ), legendgroup=transmission_type, name=tech, showlegend=False ) if set(locs_coordinates.index) == set(["x", "y"]): h_coord, v_coord = "x", "y" elif set(locs_coordinates.index) == set(["lon", "lat"]): h_coord, v_coord = "lon", "lat" line[h_coord] = [ locs_coordinates[from_location][h_coord], locs_coordinates[to_location][h_coord] ] line[v_coord] = [ locs_coordinates[from_location][v_coord], locs_coordinates[to_location][v_coord] ] line_legend[h_coord] = [None] line_legend[v_coord] = [None] line_info_marker[h_coord] = [(1 / 2) * (locs_coordinates[from_location][h_coord] + locs_coordinates[to_location][h_coord])] line_info_marker[v_coord] = [(1 / 2) * (locs_coordinates[from_location][v_coord] + locs_coordinates[to_location][v_coord])] if is_initial_timestep: # plot only the first timestep data when the chart is initialized line["visible"] = True line_legend["visible"] = True line_info_marker["visible"] = True if add_legend: return [line, line_legend, line_info_marker] else: return [line, line_info_marker]
def _get_var_data(var, model, dataset, visible, subset, sum_dims, squeeze): """ Get variable data from model_data and use it to populate a list with Plotly plots """ carriers = list(dataset.carriers.values) # list to populate data = [] # Clustered data does not get plotted on a datetime axis if 'clusters' in dataset.dims: clusters = dataset.timestep_cluster.to_pandas() cluster_groups = clusters.groupby(clusters).groups # Add an extra timestep at the end of each cluster, so we can break # scatter lines with a NaN between each cluster dummy_timestep = lambda x: pd.to_datetime(x[-1] + pd.Timedelta(100, unit='ns')) reindexing_timesteps = np.concatenate([ group_timesteps.append(pd.Index([dummy_timestep(group_timesteps)])).values for group_timesteps in cluster_groups.values() ]) timesteps = pd.Index(reindexing_timesteps).values.astype(str) # replace dummy timestep with NaN timesteps[pd.Index(reindexing_timesteps).nanosecond == 100] = np.nan timesteps = pd.to_datetime(timesteps, errors='ignore') if var == 'storage_inter_cluster': datesteps = pd.to_datetime(model._model_data.datesteps.values) else: timesteps = pd.to_datetime(model._model_data.timesteps.values) def _get_reindexed_array(array, index=['locs', 'techs'], fillna=None): # reindexing data means that DataArrays have the same values in locs and techs reindexer = {k: sorted(dataset[k].values) for k in index} formatted_array = model.get_formatted_array(array) if fillna is not None: return formatted_array.reindex(**reindexer).fillna(fillna) else: return formatted_array.reindex(**reindexer) def _get_y_vals(array, ignore_clustering=False): if 'clusters' in dataset.dims and not ignore_clustering: return array.to_pandas().reindex(reindexing_timesteps).values else: return array.values if hasattr(model, 'results'): array_prod = _get_reindexed_array('carrier_prod', index=['locs', 'techs', 'carriers'], fillna=0) array_con = _get_reindexed_array('carrier_con', index=['locs', 'techs', 'carriers'], fillna=0) if 'resource_con' in dataset.data_vars: resource_con = _get_reindexed_array('resource_con', fillna=0) else: resource_con = 0 # carrier flow is a combination of carrier_prod, carrier_con and # carrier_export for a given energy carrier if var in carriers: array_flow = (array_prod.loc[dict(carriers=var)] + array_con.loc[dict(carriers=var)]) if 'carrier_export' in dataset: export_flow = subset_sum_squeeze( _get_reindexed_array( 'carrier_export', index=['locs', 'techs', 'carriers'], fillna=0 ).loc[dict(carriers=var)], subset, sum_dims, squeeze ) if 'unmet_demand' in dataset: unmet_flow = subset_sum_squeeze( _get_reindexed_array( 'unmet_demand', index=['locs', 'carriers'], fillna=0 ).loc[dict(carriers=var)], subset, sum_dims, squeeze=False ) # array flow for storage tracks stored energy. carrier_flow is # charge/discharge (including resource consumed for supply_plus techs) elif var == 'storage': array_flow = _get_reindexed_array('storage') if 'resource_eff' in dataset.data_vars: resource_eff = _get_reindexed_array('resource_eff', fillna=1) else: resource_eff = 1 charge = subset_sum_squeeze( -array_con.sum('carriers') + resource_con * resource_eff, subset, sum_dims, squeeze=False ) discharge = -subset_sum_squeeze( array_prod.sum('carriers'), subset, sum_dims, squeeze=False ) elif var == 'resource_con': array_flow = resource_con else: array_flow = _get_reindexed_array(var) array_flow = subset_sum_squeeze(array_flow, subset, sum_dims, squeeze) err_details = ' (variable: `{}`, subset: `{}`, sum_dims: `{}`.'.format(var, subset, sum_dims) if 'timesteps' not in array_flow.dims and 'datesteps' not in array_flow.dims: raise ValueError( '`timesteps` not in plotting data, cannot proceed' + err_details ) if len(array_flow.dims) > 2: if 'costs' in array_flow.dims: err_details = err_details + (' Try subsetting to select a cost class, ' "e.g. subset={'costs': ['monetary']}.") raise ValueError( 'Too many dimensions to plot: `{}`'.format(array_flow.dims) + err_details ) # If techs not given as a subset (implying a desire to order manually), # sort techs such that those varying output least are at the bottom of the stack if subset.get('techs', None) or var == 'storage_inter_cluster': sorted_techs = array_flow.techs.values else: sorted_techs = [ array_flow.techs.values[i] for i in array_flow.var(dim='timesteps').argsort() ] # for tech in array_flow.techs.values: for tech in sorted_techs: tech_dict = {'techs': tech} if not array_flow.loc[tech_dict].sum(): continue # We allow transmission tech information to show up in some cases if 'techs_transmission' in dataset and tech in dataset.techs_transmission.values: base_tech = 'transmission' color = dataset.colors.loc[{'techs': tech.split(':')[0]}].item() name = break_name(dataset.names.loc[{'techs': tech.split(':')[0]}].item()) if var in carriers: continue # no transmission in carrier flow else: base_tech = dataset.inheritance.loc[tech_dict].item().split('.')[0] color = dataset.colors.loc[tech_dict].item() name = break_name(dataset.names.loc[tech_dict].item()) if base_tech == 'demand': # Always insert demand at position 0 in the list, to make # sure it appears on top in the legend data.insert(0, go.Scatter( x=timesteps, y=_get_y_vals(-array_flow.loc[tech_dict]), visible=visible, line=dict(color=color), name=name, legendgroup=tech) ) elif var == 'storage': # stored energy as scatter, carrier/resource prod/con as stacked bar data.insert(0, go.Scatter( x=timesteps, y=_get_y_vals(array_flow.loc[tech_dict]), visible=visible, line=dict(color=color), mode='lines', name=name + ' stored energy', showlegend=False, text=tech + ' stored energy', hoverinfo='x+y+text', legendgroup=tech) ) data.append(go.Bar( x=timesteps, y=_get_y_vals(charge.loc[tech_dict]), visible=visible, name=name, marker=dict(color=color), legendgroup=tech, text=tech + ' charge', hoverinfo='x+y+text' )) data.append(go.Bar( x=timesteps, y=_get_y_vals(discharge.loc[tech_dict]), visible=visible, name=name, marker=dict(color=color, opacity=0.8), legendgroup=tech, text=tech + ' discharge', hoverinfo='x+y+text', showlegend=False )) elif var == 'storage_inter_cluster': data.append(go.Scatter( x=datesteps, y=_get_y_vals(array_flow.loc[tech_dict], ignore_clustering=True), visible=visible, line=dict(color=color), mode='lines', name=name, showlegend=False, text=tech, hoverinfo='x+y+text', legendgroup=tech )) else: data.append(go.Bar( x=timesteps, y=_get_y_vals(array_flow.loc[tech_dict]), visible=visible, name=name, legendgroup=tech, marker=dict(color=color) )) if var in carriers and 'carrier_export' in dataset and export_flow.loc[tech_dict].sum(): data.append(go.Bar( x=timesteps, y=_get_y_vals(-export_flow.loc[tech_dict]), visible=visible, name=name + ' export', legendgroup=tech, marker=dict(color=hex_to_rgba(color, 0.5)) )) if var in carriers and 'unmet_demand' in dataset: data.append(go.Bar( x=timesteps, y=_get_y_vals(unmet_flow), visible=visible, name='Unmet ' + var + ' demand', legendgroup='unmet_demand', marker=dict(color='grey') )) return data
def _get_var_data( cap, model, dataset, visible, subset, sum_dims, squeeze, locations, orientation): if 'systemwide' in cap: array_cap = subset_sum_squeeze(dataset[cap], subset) if 'costs' in array_cap.dims and len(array_cap['costs']) == 1: array_cap = array_cap.squeeze('costs') elif 'costs' in array_cap.dims and len(array_cap['costs']) > 1: raise ValueError( 'Cannot plot {} without subsetting to pick one cost type ' 'of interest'.format(cap) ) if 'carriers' not in subset.keys(): array_cap = array_cap.sortby('carriers') else: array_cap = model.get_formatted_array(cap).reindex(locs=locations) array_cap = subset_sum_squeeze(array_cap, subset, sum_dims, squeeze) if len(array_cap.dims) > 2: raise ValueError( 'Maximum two dimensions allowed for plotting capacity, but {} ' 'given as dimensions for {}'.format(array_cap.dims, cap) ) if 'techs' not in array_cap.dims: raise ValueError('Cannot plot capacity without `techs` in dimensions') elif 'techs' not in subset.keys(): array_cap = array_cap.sortby('techs') data = [] for tech in array_cap.techs.values: if tech not in dataset.techs.values: continue if 'techs_transmission' in dataset and tech in dataset.techs_transmission.values: continue else: base_tech = dataset.inheritance.loc[{'techs': tech}].item().split('.')[0] if base_tech in 'demand': continue if array_cap.loc[{'techs': tech}].sum() > 0: x = array_cap.loc[{'techs': tech}].values name = break_name(model._model_data.names.loc[{'techs': tech}].item(), 30) if 'systemwide' in cap: y = natsorted(array_cap.carriers.values) else: if 'locs' in array_cap.dims: y = natsorted(array_cap.locs.values) else: # Single location y = [array_cap.locs.values] if orientation == 'v': x, y = y, x # Flip axes hoverinfo = 'y+name' else: hoverinfo = 'x+name' x, y = x[::-1], y[::-1] # Make sure that sorting is from bottom down data.append(go.Bar( x=x, y=y, visible=visible, name=name, legendgroup=tech, text=tech, hoverinfo=hoverinfo, marker=dict(color=model._model_data.colors.loc[{'techs': tech}].item()), orientation=orientation )) return data