Exemplo n.º 1
0
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]
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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]
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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