import networkx as nx
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import os
from glob import glob

pd.set_option('display.mpl_style', 'default') 
pd.set_option('display.width', 5000) 
pd.set_option('display.max_columns', 60)

# individual article network data files
#gml_files = glob('../output/network/*/*.gml')
#pos_files = glob('../output/network/positive/*.gml')
#neg_files = glob('../output/network/negative/*.gml')
#neu_files = glob('../output/network/neutral/*.gml')

def calculate_graph_inf(graph):
    graph.name = filename
    info = nx.info(graph)
    print info

def plot_graph(graph):
    info = nx.info(graph)
    print info
    plt.figure(figsize=(10,10))
    nx.draw_spring(graph, with_labels = True)

# don't run
pos_graphs = []
pos_ugraphs = []
neg_graphs = []
neg_ugraphs = []
neu_graphs = []
neu_ugraphs = []

for graph_num, gml_graph in enumerate(pos_files):
    graph = nx.read_gml(gml_graph)
    ugraph = graph.to_undirected()
    U = graph.to_undirected(reciprocal=True)
    e = U.edges()
    ugraph.add_edges_from(e)
    (filepath, filename) = os.path.split(gml_graph)
    print('-' * 40)
    print(gml_graph)
    print(nx.info(graph))
    pos_graphs.append(graph)
    pos_ugraphs.append(ugraph)
    
for graph_num, gml_graph in enumerate(neg_files):
    graph = nx.read_gml(gml_graph)
    ugraph = graph.to_undirected()
    U = graph.to_undirected(reciprocal=True)
    e = U.edges()
    ugraph.add_edges_from(e)
    (filepath, filename) = os.path.split(gml_graph)
    print('-' * 40)
    print(gml_graph)
    print(nx.info(graph))
    neg_graphs.append(graph)
    neg_ugraphs.append(ugraph)
    
for graph_num, gml_graph in enumerate(neu_files):
    graph = nx.read_gml(gml_graph)
    ugraph = graph.to_undirected()
    U = graph.to_undirected(reciprocal=True)
    e = U.edges()
    ugraph.add_edges_from(e)
    (filepath, filename) = os.path.split(gml_graph)
    print('-' * 40)
    print(gml_graph)
    print(nx.info(graph))
    neu_graphs.append(graph)
    neu_ugraphs.append(ugraph)

# don't run. this is for merging gml files into big graphs
# compose(G1, G2): combine graphs identifying nodes common to both
pos_all = nx.compose_all(pos_graphs)
pos_uall = nx.compose_all(pos_ugraphs)
neg_all = nx.compose_all(neg_graphs)
neg_uall = nx.compose_all(neg_ugraphs)
neu_all = nx.compose_all(neu_graphs)
neu_uall = nx.compose_all(neu_ugraphs)

# write to gml
nx.write_gml(pos_all, "../output/network/positive_all.gml")
nx.write_gml(pos_uall, "../output/network/positive_uall.gml")
nx.write_gml(neg_all, "../output/network/negative_all.gml")
nx.write_gml(neg_uall, "../output/network/negative_uall.gml")
nx.write_gml(neu_all, "../output/network/neutral_all.gml")
nx.write_gml(neu_uall, "../output/network/neutral_uall.gml")

"""
Explanation: sentiment_graphs

(make_union & single_calc copy)
import positives, negatives, neutrals gml files
create directed and undirected gml files
nx.compose_all()


component and connectivity analysis
plot graph components and subgraphs
End of explanation
"""


#graph = nx.read_gml("../output/network/positive_all.gml")
#ugraph = nx.read_gml("../output/network/positive_uall.gml")

graph = nx.read_gml("../output/network/article_neg1.gml")
ugraph = graph.to_undirected()
U = graph.to_undirected(reciprocal=True)
e = U.edges()
ugraph.add_edges_from(e)

def drawIt(graph, what = 'graph'):
    nsize = graph.number_of_nodes()
    print "Drawing %s of size %s:" % (what, nsize)
    
    if nsize > 20:
        plt.figure(figsize=(10, 10))
        if nsize > 40:
            nx.draw_spring(graph, with_labels = True, node_size = 70, font_size = 12)
        else:
            nx.draw_spring(graph, with_labels = True)
    else:
        nx.draw_spring(graph, with_labels = True)
    plt.show()

def describeGraph(graph):
    components = sorted(nx.connected_components(graph), key = len, reverse = True)
    cc = [len(c) for c in components]
    subgraphs = list(nx.connected_component_subgraphs(graph))
    params = (graph.number_of_edges(),graph.number_of_nodes(),len(cc))
    print "Graph has %s nodes, %s edges, %s connected components\n" % params
    drawIt(graph)
    for sub in components:
        drawIt(graph.subgraph(sub), what = 'component')

"""
Explanation: start here
End of explanation
"""


# list of connected components (sets of nodes), starting with largest
print "List of connected components =", [len(c) for c in sorted(nx.connected_components(ugraph), key=len, reverse=True)]

# generate connected components as subgraphs; Gc is largest component
subgraphs = list(nx.connected_component_subgraphs(ugraph))

"""
Explanation: Components & connectivity
End of explanation
"""


Gc = max(nx.connected_component_subgraphs(ugraph), key=len)
print "Size of greatest component =", len(Gc)

"""
Explanation: Greatest component
End of explanation
"""


# returns all minimum k cutsets of an undirected graph
# i.e., the set(s) of nodes of cardinality equal to the node connectivity of G
# thus if removed, would break G into two or more connected components
cutsets = list(nx.all_node_cuts(Gc))
print "# of cutsets =", len(cutsets)

# returns a set of nodes or edges of minimum cardinality that disconnects G
print "Min node cut =", nx.minimum_node_cut(Gc, s='vaccines', t='autism')
print "Min edge cut =", nx.minimum_edge_cut(Gc)

nx.minimum_node_cut(Gc, s='vaccines', t='autism')

a = nx.minimum_edge_cut(Gc, s='autism', t='vaccines')
a

labels = nx.get_edge_attributes(Gc,'edge')
edgelabels = {}
for e in labels.keys():
    e1 = e[0:2]
    edgelabels[e1]=labels[e]
edgelabels

for e in a:
    if edgelabels.has_key(e):
        print e,edgelabels[e]
    else:
        rev_e = e[::-1]
        print rev_e, edgelabels[rev_e]

# this takes forever
# average connectivity k of a graph G is the average of local node connectivity over all pairs of nodes of G

#nx.average_node_connectivity(Gc)

# NEW SUMMARY

print "List of connected components =", [len(c) for c in sorted(nx.connected_components(ugraph), key=len, reverse=True)]
print "Size of greatest component =", len(Gc)
print "# of cutsets =", len(cutsets)
print "Min node cut =", nx.minimum_node_cut(Gc)
print "Min edge cut =", nx.minimum_edge_cut(Gc)

"""
Explanation: Moody and White provide an algorithm for identifying k-components in a graph, which is based on Kanevsky’s algorithm for finding all minimum-size node cut-sets of a graph (implemented in all_node_cuts() function):

Compute node connectivity, k, of the input graph G.
Identify all k-cutsets at the current level of connectivity using Kanevsky’s algorithm.
Generate new graph components based on the removal of these cutsets. Nodes in a cutset belong to both sides of the induced cut.
If the graph is neither complete nor trivial, return to 1; else end.
End of explanation
"""


# OLD summary DON'T DELETE YET

print "List of connected components =", [len(c) for c in sorted(nx.connected_components(ugraph), key=len, reverse=True)]
print "Size of greatest component =", len(Gc)
print "# of cutsets =", len(cutsets)
print "Min node cut =", nx.minimum_node_cut(Gc)
print "Min edge cut =", nx.minimum_edge_cut(Gc)

"""
Explanation: 
End of explanation
"""


