<commit_before>'''
Created on 31.08.2017

@author: Peer
'''

import itertools
from collections import defaultdict, OrderedDict
import datetime
import math

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.patches

from gitexplorer.basics import GitExplorerBase


class AbstractSorter(object):

    @staticmethod
    def sort(nodes, edges):
        raise NotImplemented()


class LexicographicSorter(AbstractSorter):

    @staticmethod
    def sort(nodes, edges):
        nodes = OrderedDict(sorted(nodes.items(), key=lambda node: node[0]))
        edges = OrderedDict(sorted(edges.items(), key=lambda edge: edge[0][0]))

#         for items in zip(nodes.items(), edges.items()):
#             print(items)

        return nodes, edges


def draw_chord_diagram(data, sorter=LexicographicSorter, aggregate_below=0):
    '''Draw chord diagram [1]_ from input data.

    Parameters
    ----------
    data: dict
        A dictionary where in "nodes" is the information to be displayed as arc segments. It must contain another key
        called "edges" which is a dict describing the dependencies and their weights.

    References
    -----
    .. [1] https://en.wikipedia.org/wiki/Chord_diagram
    '''
    if len(data['nodes']) == 0:
        return

    data['nodes'], data['edges'] = sorter.sort(data['nodes'], data['edges'])

    figure = plt.figure()
    axes = figure.add_subplot(111, aspect='equal')

    linspace = [float(idx) / (len(data['nodes']) - 1.0) for idx in range(len(data['nodes']))]

    color = iter(cm.rainbow(linspace))

    node_value_sum = float(sum(data['nodes'].values()))
    start = 0.0
    radius = 50

    node_position = {}

    for node_name, node_value in data['nodes'].items():

        end = start + node_value / node_value_sum * 360

        arc = matplotlib.patches.Arc(xy=(0, 0),
                                     height=2 * radius,
                                     width=2 * radius,
                                     angle=0.0,
                                     theta1=start,
                                     theta2=end - 2.0,
                                     linewidth=8,
                                     color=next(color))

        axes.add_artist(arc)

        node_position[node_name] = math.radians((start + end) / 2.0)
        start = end

    max_edge_weight = float(max(data['edges'].values()))

    for (source, target), weight in data['edges'].items():
        source_x = math.cos(node_position[source]) * radius * 0.92
        source_y = math.sin(node_position[source]) * radius * 0.92

        target_x = math.cos(node_position[target]) * radius * 0.92
        target_y = math.sin(node_position[target]) * radius * 0.92

        distance = math.sqrt((source_x - target_x) ** 2 + (source_y - target_y) ** 2)

        value = abs(node_position[source] - node_position[target]) - math.pi
        sign = value / abs(value)

        connection_style = matplotlib.patches.ConnectionStyle('Arc3', rad=sign * (1.0 - distance / (2.0 * radius)))

        connection = matplotlib.patches.ConnectionPatch(xyA=(source_x, source_y),
                                                        xyB=(target_x, target_y),
                                                        coordsA='data',
                                                        connectionstyle=connection_style,
                                                        linewidth=16 * weight / max_edge_weight,
                                                        color='grey',
                                                        alpha=0.6,
                                                        capstyle='butt')

        axes.add_artist(connection)
<commit_msg>Fixed visulaization issue and filter nodes based on aggregation_below parameter<commit_after>'''
Created on 31.08.2017

@author: Peer
'''

import itertools
from collections import defaultdict, OrderedDict
import datetime
import math

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.patches

from gitexplorer.basics import GitExplorerBase


class AbstractSorter(object):

    @staticmethod
    def sort(nodes, edges):
        raise NotImplemented()


class LexicographicSorter(AbstractSorter):

    @staticmethod
    def sort(nodes, edges):
        nodes = OrderedDict(sorted(nodes.items(), key=lambda node: node[0]))
        edges = OrderedDict(sorted(edges.items(), key=lambda edge: edge[0][0]))

#         for items in zip(nodes.items(), edges.items()):
#             print(items)

        return nodes, edges


def draw_chord_diagram(data, sorter=LexicographicSorter, aggregate_below=0):
def draw_chord_diagram(data, sorter=LexicographicSorter, aggregate_below=1):
    '''Draw chord diagram [1]_ from input data.

    Parameters
    ----------
    data: dict
        A dictionary where in "nodes" is the information to be displayed as arc segments. It must contain another key
        called "edges" which is a dict describing the dependencies and their weights.

    References
    -----
    .. [1] https://en.wikipedia.org/wiki/Chord_diagram
    '''
    if len(data['nodes']) == 0:
        return

    new_edges = {}
    for edge, value in data['edges'].items():
        if(value > aggregate_below):
            new_edges[edge] = value

    data['edges'] = new_edges

    active_nodes = set()
    for source, target in data['edges'].keys():
        active_nodes.add(source)
        active_nodes.add(target)

    new_nodes = {}
    for node, value in data['nodes'].items():
        if(node in active_nodes):
            new_nodes[node] = value

    data['nodes'] = new_nodes

    data['nodes'], data['edges'] = sorter.sort(data['nodes'], data['edges'])

    figure = plt.figure()
    axes = figure.add_subplot(111, aspect='equal')

    linspace = [float(idx) / (len(data['nodes']) - 1.0) for idx in range(len(data['nodes']))]

    color = iter(cm.rainbow(linspace))

    node_value_sum = float(sum(data['nodes'].values()))
    start = 0.0
    radius = 50

    node_position = {}

    for node_name, node_value in data['nodes'].items():

        end = start + node_value / node_value_sum * 360

        arc = matplotlib.patches.Arc(xy=(0, 0),
                                     height=2 * radius,
                                     width=2 * radius,
                                     angle=0.0,
                                     theta1=start + 1.0,
                                     theta2=end - 1.0,
                                     linewidth=8,
                                     color=next(color))

        axes.add_artist(arc)

        node_position[node_name] = math.radians((start + end) / 2.0)
        start = end

    max_edge_weight = float(max(data['edges'].values()))

    for (source, target), weight in data['edges'].items():
        if(node_position[source] >= node_position[target]):
            node_position[source], node_position[target] = node_position[target], node_position[source]
        source_x = math.cos(node_position[source]) * radius * 0.92
        source_y = math.sin(node_position[source]) * radius * 0.92

        target_x = math.cos(node_position[target]) * radius * 0.92
        target_y = math.sin(node_position[target]) * radius * 0.92

        distance = math.sqrt((source_x - target_x) ** 2 + (source_y - target_y) ** 2)

        value = abs(node_position[source] - node_position[target]) - math.pi
        sign = value / abs(value)

        connection_style = matplotlib.patches.ConnectionStyle('Arc3', rad=sign * (1.0 - distance / (2.0 * radius)))

        connection = matplotlib.patches.ConnectionPatch(xyA=(source_x, source_y),
                                                        xyB=(target_x, target_y),
                                                        coordsA='data',
                                                        connectionstyle=connection_style,
                                                        linewidth=16 * weight / max_edge_weight,
                                                        color='grey',
                                                        alpha=0.6,
                                                        capstyle='butt')

        axes.add_artist(connection)

{'fraction_non_alphanumeric': 0.11421628189550426, 'fraction_numerical': 0.015674362089914944, 'mean_word_length': 1.8256093374527977, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 42, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5618287', 'n_tokens_mistral': 2358, 'n_tokens_neox': 2197, 'n_words': 516}