# Path: rivus/main/rivus.py
# def get_constants(prob):
#     """Retrieve time-independent variables/quantities.
# 
#     Args:
#         prob: a rivus model instance
# 
#     Returns:
#         (costs, pmax, kappa_hub, kappa_process) tuple
# 
#     Example:
#         costs, pmax, kappa_hub, kappa_process = get_constants(prob)
#     """
#     costs = get_entity(prob, 'costs')
#     Pmax = get_entity(prob, 'Pmax')
#     Kappa_hub = get_entity(prob, 'Kappa_hub')
#     Kappa_process = get_entity(prob, 'Kappa_process')
# 
#     # nicer index names
#     Pmax.index.names = ['Vertex1', 'Vertex2', 'commodity']
#     Kappa_hub.index.names = ['Vertex1', 'Vertex2', 'process']
# 
#     # drop all-zero rows
#     Pmax = Pmax[Pmax > 0].unstack().fillna(0)
#     Kappa_hub = Kappa_hub[Kappa_hub > 0].unstack().fillna(0)
#     Kappa_process = Kappa_process[Kappa_process > 0].unstack().fillna(0)
# 
#     # Drop all 0 commodities
#     for column in Pmax:
#         if all(Pmax[column] == 0):
#             del Pmax[column]
# 
#     # round to integers
#     if Pmax.empty:
#         Pmax = pd.DataFrame([])
#     else:
#         Pmax = Pmax.applymap(round)
#     if Kappa_hub.empty:
#         Kappa_hub = pd.DataFrame([])
#     else:
#         Kappa_hub = Kappa_hub.applymap(round)
#     if Kappa_process.empty:
#         Kappa_process = pd.DataFrame([])
#     else:
#         Kappa_process = Kappa_process.applymap(round)
#     costs = costs.apply(round)
# 
#     return costs, Pmax, Kappa_hub, Kappa_process
# 
# def get_timeseries(prob):
#     """Retrieve time-dependent variables/quantities.
# 
#     Example:
#         source, flows, hubs, proc_io, proc_tau = get_timeseries(prob)
# 
#     Args:
#         prob: a rivus model instance
# 
#     Returns:
#         (source, flows, hubs, proc_io, proc_tau) tuple
#     """
# 
#     source = get_entity(prob, 'Rho')
#     flows = get_entities(prob, ['Pin', 'Pot', 'Psi', 'Sigma'])
#     hubs = get_entity(prob, 'Epsilon_hub')
#     proc_io = get_entities(prob, ['Epsilon_in', 'Epsilon_out'])
#     proc_tau = get_entity(prob, 'Tau')
# 
#     # fill NaN's
#     flows.fillna(0, inplace=True)
#     proc_io.fillna(0, inplace=True)
# 
#     # drop all-zero rows
#     source = source[source > 0].unstack()
#     flows = flows[flows.sum(axis=1) > 0].applymap(round)
# 
#     hubs = hubs[hubs > 0].unstack().fillna(0)
#     if hubs.empty:
#         hubs = pd.DataFrame([])
#     else:
#         hubs = hubs.applymap(round)
# 
#     proc_io = proc_io[proc_io.sum(axis=1) > 0]
#     if not proc_io.empty:
#         proc_io = proc_io.applymap(round)
# 
#     proc_tau = proc_tau[proc_tau.apply(round) > 0]
#     if not proc_tau.empty:
#         proc_tau = proc_tau.unstack().fillna(0).applymap(round)
# 
#     return source, flows, hubs, proc_io, proc_tau
# 
# def line_length(line):
#     """Calculate length of a line in meters, given in geographic coordinates.
# 
#     Args:
#         line: a shapely LineString object with WGS 84 coordinates
# 
#     Returns:
#         Length of line in meters
#     """
#     # Swap shapely (lonlat) to geopy (latlon) points
#     latlon = lambda lonlat: (lonlat[1], lonlat[0])
#     total_length = sum(distance(latlon(a), latlon(b)).meters
#                        for (a, b) in pairs(line.coords))
#     return round(total_length, 0)
# 
# Path: rivus/utils/pandashp.py
# def total_bounds(df):
#     """Return bounding box (minx, miny, maxx, maxy) of all geometries. """
#     b = bounds(df)
#     return (b['minx'].min(),
#             b['miny'].min(),
#             b['maxx'].max(),
#             b['maxy'].max())


from pandas import Series
from numpy import union1d
from mpl_toolkits.basemap import Basemap
from rivus.main.rivus import get_constants, get_timeseries, line_length
from rivus.utils.pandashp import total_bounds
import math
        import time

        import plotly.offline as po
        fig = fig3d(prob, ['Gas', 'Heat', 'Elec'], hub_opac=0.55, linescale=7)
        # for static image
        # po.plot(fig, filename='plotly-game.html', image='png')
        po.plot(fig, filename='plotly-game.html')

    Returns
    -------
    plotly compatible figure *dict* (in plotly everything is kinda a dict.)

    Note
    -----
        Greatly inspired by
        `Example1 <https://plot.ly/python/lines-on-maps/>`_ and
        `Example2 <https://plot.ly/python/3d-network-graph/>`_.
    """
    if verbose:
        plotprep = time.time()

    # Map projection
    bbox, cent_para, cent_meri = _getbb(prob)
    bm = Basemap(
        projection='tmerc', resolution=None,
        llcrnrlat=bbox[0], llcrnrlon=bbox[1],
        urcrnrlat=bbox[2], urcrnrlon=bbox[3],
        lat_0=cent_para, lon_0=cent_meri)

    # Get result values for plotting
    _, pmax, kappa_hub, kappa_process = get_constants(prob)

# Path: rivus/main/rivus.py
# def get_constants(prob):
#     """Retrieve time-independent variables/quantities.
# 
#     Args:
#         prob: a rivus model instance
# 
#     Returns:
#         (costs, pmax, kappa_hub, kappa_process) tuple
# 
#     Example:
#         costs, pmax, kappa_hub, kappa_process = get_constants(prob)
#     """
#     costs = get_entity(prob, 'costs')
#     Pmax = get_entity(prob, 'Pmax')
#     Kappa_hub = get_entity(prob, 'Kappa_hub')
#     Kappa_process = get_entity(prob, 'Kappa_process')
# 
#     # nicer index names
#     Pmax.index.names = ['Vertex1', 'Vertex2', 'commodity']
#     Kappa_hub.index.names = ['Vertex1', 'Vertex2', 'process']
# 
#     # drop all-zero rows
#     Pmax = Pmax[Pmax > 0].unstack().fillna(0)
#     Kappa_hub = Kappa_hub[Kappa_hub > 0].unstack().fillna(0)
#     Kappa_process = Kappa_process[Kappa_process > 0].unstack().fillna(0)
# 
#     # Drop all 0 commodities
#     for column in Pmax:
#         if all(Pmax[column] == 0):
#             del Pmax[column]
# 
#     # round to integers
#     if Pmax.empty:
#         Pmax = pd.DataFrame([])
#     else:
#         Pmax = Pmax.applymap(round)
#     if Kappa_hub.empty:
#         Kappa_hub = pd.DataFrame([])
#     else:
#         Kappa_hub = Kappa_hub.applymap(round)
#     if Kappa_process.empty:
#         Kappa_process = pd.DataFrame([])
#     else:
#         Kappa_process = Kappa_process.applymap(round)
#     costs = costs.apply(round)
# 
#     return costs, Pmax, Kappa_hub, Kappa_process
# 
# def get_timeseries(prob):
#     """Retrieve time-dependent variables/quantities.
# 
#     Example:
#         source, flows, hubs, proc_io, proc_tau = get_timeseries(prob)
# 
#     Args:
#         prob: a rivus model instance
# 
#     Returns:
#         (source, flows, hubs, proc_io, proc_tau) tuple
#     """
# 
#     source = get_entity(prob, 'Rho')
#     flows = get_entities(prob, ['Pin', 'Pot', 'Psi', 'Sigma'])
#     hubs = get_entity(prob, 'Epsilon_hub')
#     proc_io = get_entities(prob, ['Epsilon_in', 'Epsilon_out'])
#     proc_tau = get_entity(prob, 'Tau')
# 
#     # fill NaN's
#     flows.fillna(0, inplace=True)
#     proc_io.fillna(0, inplace=True)
# 
#     # drop all-zero rows
#     source = source[source > 0].unstack()
#     flows = flows[flows.sum(axis=1) > 0].applymap(round)
# 
#     hubs = hubs[hubs > 0].unstack().fillna(0)
#     if hubs.empty:
#         hubs = pd.DataFrame([])
#     else:
#         hubs = hubs.applymap(round)
# 
#     proc_io = proc_io[proc_io.sum(axis=1) > 0]
#     if not proc_io.empty:
#         proc_io = proc_io.applymap(round)
# 
#     proc_tau = proc_tau[proc_tau.apply(round) > 0]
#     if not proc_tau.empty:
#         proc_tau = proc_tau.unstack().fillna(0).applymap(round)
# 
#     return source, flows, hubs, proc_io, proc_tau
# 
# def line_length(line):
#     """Calculate length of a line in meters, given in geographic coordinates.
# 
#     Args:
#         line: a shapely LineString object with WGS 84 coordinates
# 
#     Returns:
#         Length of line in meters
#     """
#     # Swap shapely (lonlat) to geopy (latlon) points
#     latlon = lambda lonlat: (lonlat[1], lonlat[0])
#     total_length = sum(distance(latlon(a), latlon(b)).meters
#                        for (a, b) in pairs(line.coords))
#     return round(total_length, 0)
# 
# Path: rivus/utils/pandashp.py
# def total_bounds(df):
#     """Return bounding box (minx, miny, maxx, maxy) of all geometries. """
#     b = bounds(df)
#     return (b['minx'].min(),
#             b['miny'].min(),
#             b['maxx'].max(),
#             b['maxy'].max())


# Path: rivus/io/plot.py
from pandas import Series
from numpy import union1d
from mpl_toolkits.basemap import Basemap
from rivus.main.rivus import get_constants, get_timeseries, line_length
from rivus.utils.pandashp import total_bounds
import math
        import time


        import plotly.offline as po
        fig = fig3d(prob, ['Gas', 'Heat', 'Elec'], hub_opac=0.55, linescale=7)
        # for static image
        # po.plot(fig, filename='plotly-game.html', image='png')
        po.plot(fig, filename='plotly-game.html')

    Returns
    -------
    plotly compatible figure *dict* (in plotly everything is kinda a dict.)

    Note
    -----
        Greatly inspired by
        `Example1 <https://plot.ly/python/lines-on-maps/>`_ and
        `Example2 <https://plot.ly/python/3d-network-graph/>`_.
    """
    if verbose:
        plotprep = time.time()

    # Map projection
    bbox, cent_para, cent_meri = _getbb(prob)
    bm = Basemap(
        projection='tmerc', resolution=None,
        llcrnrlat=bbox[0], llcrnrlon=bbox[1],
        urcrnrlat=bbox[2], urcrnrlon=bbox[3],
        lat_0=cent_para, lon_0=cent_meri)

    # Get result values for plotting
    _, pmax, kappa_hub, kappa_process = get_constants(prob)

    source = get_timeseries(prob)[0]