1cef7893435aa41160dd1255c43cb8498279738ccChris Craik'''
2cef7893435aa41160dd1255c43cb8498279738ccChris Craikaltgraph.GraphStat - Functions providing various graph statistics
3cef7893435aa41160dd1255c43cb8498279738ccChris Craik=================================================================
4cef7893435aa41160dd1255c43cb8498279738ccChris Craik'''
5cef7893435aa41160dd1255c43cb8498279738ccChris Craikimport sys
6cef7893435aa41160dd1255c43cb8498279738ccChris Craik
7cef7893435aa41160dd1255c43cb8498279738ccChris Craikdef degree_dist(graph, limits=(0,0), bin_num=10, mode='out'):
8cef7893435aa41160dd1255c43cb8498279738ccChris Craik    '''
9cef7893435aa41160dd1255c43cb8498279738ccChris Craik    Computes the degree distribution for a graph.
10cef7893435aa41160dd1255c43cb8498279738ccChris Craik
11cef7893435aa41160dd1255c43cb8498279738ccChris Craik    Returns a list of tuples where the first element of the tuple is the center of the bin
12cef7893435aa41160dd1255c43cb8498279738ccChris Craik    representing a range of degrees and the second element of the tuple are the number of nodes
13cef7893435aa41160dd1255c43cb8498279738ccChris Craik    with the degree falling in the range.
14cef7893435aa41160dd1255c43cb8498279738ccChris Craik
15cef7893435aa41160dd1255c43cb8498279738ccChris Craik    Example::
16cef7893435aa41160dd1255c43cb8498279738ccChris Craik
17cef7893435aa41160dd1255c43cb8498279738ccChris Craik        ....
18cef7893435aa41160dd1255c43cb8498279738ccChris Craik    '''
19cef7893435aa41160dd1255c43cb8498279738ccChris Craik
20cef7893435aa41160dd1255c43cb8498279738ccChris Craik    deg = []
21cef7893435aa41160dd1255c43cb8498279738ccChris Craik    if mode == 'inc':
22cef7893435aa41160dd1255c43cb8498279738ccChris Craik        get_deg = graph.inc_degree
23cef7893435aa41160dd1255c43cb8498279738ccChris Craik    else:
24cef7893435aa41160dd1255c43cb8498279738ccChris Craik        get_deg = graph.out_degree
25cef7893435aa41160dd1255c43cb8498279738ccChris Craik
26cef7893435aa41160dd1255c43cb8498279738ccChris Craik    for node in graph:
27cef7893435aa41160dd1255c43cb8498279738ccChris Craik        deg.append( get_deg(node) )
28cef7893435aa41160dd1255c43cb8498279738ccChris Craik
29cef7893435aa41160dd1255c43cb8498279738ccChris Craik    if not deg:
30cef7893435aa41160dd1255c43cb8498279738ccChris Craik        return []
31cef7893435aa41160dd1255c43cb8498279738ccChris Craik
32cef7893435aa41160dd1255c43cb8498279738ccChris Craik    results = _binning(values=deg, limits=limits, bin_num=bin_num)
33cef7893435aa41160dd1255c43cb8498279738ccChris Craik
34cef7893435aa41160dd1255c43cb8498279738ccChris Craik    return results
35cef7893435aa41160dd1255c43cb8498279738ccChris Craik
36cef7893435aa41160dd1255c43cb8498279738ccChris Craik_EPS = 1.0/(2.0**32)
37cef7893435aa41160dd1255c43cb8498279738ccChris Craikdef _binning(values, limits=(0,0), bin_num=10):
38cef7893435aa41160dd1255c43cb8498279738ccChris Craik    '''
39cef7893435aa41160dd1255c43cb8498279738ccChris Craik    Bins data that falls between certain limits, if the limits are (0, 0) the
40cef7893435aa41160dd1255c43cb8498279738ccChris Craik    minimum and maximum values are used.
41cef7893435aa41160dd1255c43cb8498279738ccChris Craik
42cef7893435aa41160dd1255c43cb8498279738ccChris Craik    Returns a list of tuples where the first element of the tuple is the center of the bin
43cef7893435aa41160dd1255c43cb8498279738ccChris Craik    and the second element of the tuple are the counts.
44cef7893435aa41160dd1255c43cb8498279738ccChris Craik    '''
45cef7893435aa41160dd1255c43cb8498279738ccChris Craik    if limits == (0, 0):
46cef7893435aa41160dd1255c43cb8498279738ccChris Craik        min_val, max_val = min(values) - _EPS, max(values) + _EPS
47cef7893435aa41160dd1255c43cb8498279738ccChris Craik    else:
48cef7893435aa41160dd1255c43cb8498279738ccChris Craik        min_val, max_val = limits
49cef7893435aa41160dd1255c43cb8498279738ccChris Craik
50cef7893435aa41160dd1255c43cb8498279738ccChris Craik    # get bin size
51cef7893435aa41160dd1255c43cb8498279738ccChris Craik    bin_size = (max_val - min_val)/float(bin_num)
52cef7893435aa41160dd1255c43cb8498279738ccChris Craik    bins = [0] * (bin_num)
53cef7893435aa41160dd1255c43cb8498279738ccChris Craik
54cef7893435aa41160dd1255c43cb8498279738ccChris Craik    # will ignore these outliers for now
55cef7893435aa41160dd1255c43cb8498279738ccChris Craik    out_points = 0
56cef7893435aa41160dd1255c43cb8498279738ccChris Craik    for value in values:
57cef7893435aa41160dd1255c43cb8498279738ccChris Craik        try:
58cef7893435aa41160dd1255c43cb8498279738ccChris Craik            if (value - min_val) < 0:
59cef7893435aa41160dd1255c43cb8498279738ccChris Craik                out_points += 1
60cef7893435aa41160dd1255c43cb8498279738ccChris Craik            else:
61cef7893435aa41160dd1255c43cb8498279738ccChris Craik                index = int((value - min_val)/float(bin_size))
62cef7893435aa41160dd1255c43cb8498279738ccChris Craik                bins[index] += 1
63cef7893435aa41160dd1255c43cb8498279738ccChris Craik        except IndexError:
64cef7893435aa41160dd1255c43cb8498279738ccChris Craik            out_points += 1
65cef7893435aa41160dd1255c43cb8498279738ccChris Craik
66cef7893435aa41160dd1255c43cb8498279738ccChris Craik    # make it ready for an x,y plot
67cef7893435aa41160dd1255c43cb8498279738ccChris Craik    result = []
68cef7893435aa41160dd1255c43cb8498279738ccChris Craik    center = (bin_size/2) + min_val
69cef7893435aa41160dd1255c43cb8498279738ccChris Craik    for i, y in enumerate(bins):
70cef7893435aa41160dd1255c43cb8498279738ccChris Craik        x = center + bin_size * i
71cef7893435aa41160dd1255c43cb8498279738ccChris Craik        result.append( (x,y) )
72cef7893435aa41160dd1255c43cb8498279738ccChris Craik
73cef7893435aa41160dd1255c43cb8498279738ccChris Craik    return result
74