def update_event_slider(jsonified_data):
    if jsonified_data:
        nodes = arg.json2arg(jsonified_data)
    else:
        nodes = []

    nr_leaves = len([n for n in nodes if type(n) is arg.Leaf])
    nr_events = len(nodes) - nr_leaves
    return 0, nr_events, 1, nr_events
def update_seq_slider(jsonified_data):
    if jsonified_data:
        nodes = arg.json2arg(jsonified_data)
    else:
        nodes = []
    breakpoints = get_breakpoints(nodes)
    marks = dict((b * 1000, str(i + 1)) for i, b in enumerate(breakpoints))
    if not marks:
        marks = None
    return 0, 1000, [0, 1000], marks
def update_arg_figure(jsonified_data, event, interval):

    if jsonified_data:
        nodes = arg.json2arg(jsonified_data)

        interval = [i / 1000 for i in interval]

        # Get marginal arg for interval
        marg_arg_nodes = marginal_arg(nodes, interval)
        # print(interval)
        # get only subset of events
        nr_leaves = len([n for n in nodes if type(n) is arg.Leaf])
        new_nodes = marg_arg_nodes[:nr_leaves + event]
    else:
        new_nodes = []

    return arg_figure_data(new_nodes)
def update_marg_tree_figure(jsonified_data, hover, slider_interval):

    marg_tree_list = []
    if hover and jsonified_data:
        nodes = arg.json2arg(jsonified_data)
        focus_node_idx = hover['points'][0]['pointIndex']
        focus_node = nodes[focus_node_idx]

        if type(focus_node) is Recombination:
            intervals = focus_node.child.intervals
        else:
            intervals = focus_node.parent.intervals

        # slider interval is 0-1000 not 0-1:
        slider_interval = [x / 1000 for x in slider_interval]
        # get part of intervals that intersect slider interval:
        intervals = interval_intersect([slider_interval], intervals)

        for interval in intervals:
            # get marginal arg under focus node
            new_nodes = traverse_marginal(focus_node, interval)
            new_nodes = list(new_nodes)
            new_nodes.sort(key=lambda x: x.height)

            marg_trees, _ = marginal_trees(new_nodes, interval)
            marg_tree_list.extend(marg_trees)

        nr_cols = len(marg_tree_list)

        space = 0.5

        for i in range(nr_cols):
            tree = marg_tree_list[i]
            for node in tree:
                node.xpos = node.xpos / (nr_cols +
                                         (nr_cols - 1) * space) + i / nr_cols
            marg_tree_list[i] = tree

    # TODO: Maybe keep "dangling root" branch here

    if marg_tree_list:
        return (tree_figure_data(marg_tree_list))
    else:
        return (tree_figure_data([]))
def update_ancestral_seq_figure(jsonified_data, hover, slider_interval):

    traces = []
    shape_list = []

    if hover and jsonified_data:
        nodes = arg.json2arg(jsonified_data)
        focus_node_idx = hover['points'][0]['pointIndex']
        focus_node = nodes[focus_node_idx]

        # slider interval is 0-1000 not 0-1:
        slider_interval = [x / 1000 for x in slider_interval]

        gray_segments = list(
            map(tuple, interval_diff([[0, 1]], [slider_interval])))

        def get_segments(focus_node, intervals):
            segments = list()
            marg_tree_list = list()
            for interval in intervals:
                new_nodes = traverse_marginal(focus_node, interval)
                new_nodes = list(new_nodes)
                new_nodes.sort(key=lambda x: x.height)
                marg_trees, marg_segm = marginal_trees(new_nodes, interval)
                #                 print(marg_trees, marg_segm)
                marg_tree_list.extend(marg_trees)
                segments.extend(marg_segm)
            return segments

        def get_shapes(segments, gray_segments, x, y, color_map):
            shape_list = list()
            shape = dict(type='rect',
                         xref='x',
                         yref='y',
                         fillcolor=None,
                         line={'width': 1},
                         x0=x,
                         y0=y,
                         x1=x + 2 / 5,
                         y1=y + 0.1)
            shape_list.append(shape)
            for i, segment in enumerate(segments):
                color = color_map[segment]
                shape = dict(type='rect',
                             xref='x',
                             yref='y',
                             fillcolor=color,
                             line={'width': 1},
                             x0=x + segment[0] * 2 / 5,
                             y0=y,
                             x1=x + segment[1] * 2 / 5,
                             y1=y + 0.1)
                shape_list.append(shape)
            for i, segment in enumerate(gray_segments):
                shape = dict(type='rect',
                             xref='x',
                             yref='y',
                             fillcolor='lightgray',
                             line={'width': 1},
                             x0=x + segment[0] * 2 / 5,
                             y0=y,
                             x1=x + segment[1] * 2 / 5,
                             y1=y + 0.1)
                shape_list.append(shape)
            return shape_list

        if type(focus_node) is Leaf:

            colors, _ = plotly.colors.convert_colors_to_same_type(
                plotly.colors.sequential.Rainbow)
            colorscale = plotly.colors.make_colorscale(colors)
            color = get_continuous_color(colorscale, intermed=0)

            shape_list = [
                dict(type='rect',
                     xref='x',
                     yref='y',
                     fillcolor=color,
                     line={'width': 1},
                     x0=1.5 / 5,
                     y0=0.25,
                     x1=3.5 / 5,
                     y1=0.35)
            ]
            for segment in gray_segments:
                shape = dict(type='rect',
                             xref='x',
                             yref='y',
                             fillcolor='lightgray',
                             line={'width': 1},
                             x0=1.5 / 5 + segment[0] * 2 / 5,
                             y0=0.25,
                             x1=1.5 / 5 + segment[1] * 2 / 5,
                             y1=0.35)
                shape_list.append(shape)

        elif type(focus_node) is Recombination:
            # print("###", focus_node.left_parent.intervals, focus_node.right_parent.intervals)
            segments1 = get_segments(focus_node,
                                     focus_node.left_parent.intervals)
            segments2 = get_segments(focus_node,
                                     focus_node.right_parent.intervals)
            segments3 = get_segments(focus_node, focus_node.child.intervals)

            # get part of intervals that intersect slider interval:
            segments1 = list(
                map(tuple, interval_intersect([slider_interval], segments1)))
            segments2 = list(
                map(tuple, interval_intersect([slider_interval], segments2)))
            segments3 = list(
                map(tuple, interval_intersect([slider_interval], segments3)))

            unique_segments = sorted(set().union(segments1, segments2,
                                                 segments3))
            color_map = dict()
            colors, _ = plotly.colors.convert_colors_to_same_type(
                plotly.colors.sequential.Rainbow)
            colorscale = plotly.colors.make_colorscale(colors)
            for i, s in enumerate(unique_segments):
                color_map[s] = get_continuous_color(colorscale,
                                                    intermed=i /
                                                    len(unique_segments))

            shape_list = \
                get_shapes(segments1, gray_segments, x=0, y=0.75, color_map=color_map) + \
                get_shapes(segments2, gray_segments, x=3/5, y=0.75, color_map=color_map) + \
                get_shapes(segments3, gray_segments, x=1.5/5, y=0.25, color_map=color_map) + \
                   [dict(type='line', xref='x', yref='y', line= {'width': 2, 'color': 'gray'},
                            x0=0.5, y0=0.55, x1=0.5, y1=0.35),
                    dict(type='line', xref='x', yref='y', line= {'width': 2, 'color': 'gray'},
                            x0=0.5, y0=0.55, x1=1/5, y1=0.75),
                    dict(type='line', xref='x', yref='y', line= {'width': 2, 'color': 'gray'},
                            x0=0.5, y0=0.55, x1=4/5, y1=0.75)]

            # print("slider", slider_interval)
            # shape_list.append(dict(type='rect', xref='x', yref='y', fillcolor='grey', line= {'width': 1},
            #             x0=slider_interval[0], y0=0.5, x1=slider_interval[1], y1=0.5+0.1))

        else:
            segments1 = get_segments(focus_node,
                                     focus_node.children[0].intervals)
            segments2 = get_segments(focus_node,
                                     focus_node.children[1].intervals)
            segments3 = get_segments(focus_node, focus_node.parent.intervals)

            # get part of intervals that intersect slider interval:
            segments1 = list(
                map(tuple, interval_intersect([slider_interval], segments1)))
            segments2 = list(
                map(tuple, interval_intersect([slider_interval], segments2)))
            segments3 = list(
                map(tuple, interval_intersect([slider_interval], segments3)))

            unique_segments = sorted(set().union(segments1, segments2,
                                                 segments3))
            color_map = dict()
            colors, _ = plotly.colors.convert_colors_to_same_type(
                plotly.colors.sequential.Rainbow)
            colorscale = plotly.colors.make_colorscale(colors)
            for i, s in enumerate(unique_segments):
                color_map[s] = get_continuous_color(colorscale,
                                                    intermed=i /
                                                    len(unique_segments))

            shape_list = \
                get_shapes(segments1, gray_segments, x=0, y=0.25, color_map=color_map) + \
                get_shapes(segments2, gray_segments, x=3/5, y=0.25, color_map=color_map) + \
                get_shapes(segments3, gray_segments, x=1.5/5, y=0.75, color_map=color_map) + \
                    [dict(type='line', xref='x', yref='y', line= {'width': 2, 'color': 'gray'},
                            x0=0.5, y0=0.55, x1=0.5, y1=0.75),
                    dict(type='line', xref='x', yref='y', line= {'width': 2, 'color': 'gray'},
                            x0=0.5, y0=0.55, x1=1/5, y1=0.35),
                    dict(type='line', xref='x', yref='y', line= {'width': 2, 'color': 'gray'},
                            x0=0.5, y0=0.55, x1=4/5, y1=0.35)]

    figure_data = dict(
        data=traces,
        layout=dict(
            xaxis=dict(
                fixedrange=True,
                range=[-0.01, 1.01],  #title='Samples',
                showgrid=False,
                showline=False,
                zeroline=False,
                showticklabels=False),
            yaxis=dict(
                fixedrange=True,
                range=[0, 1],  #title='Time',
                showgrid=False,
                showline=False,
                zeroline=False,
                showticklabels=False),
            margin={
                'l': 0,
                'b': 0,
                't': 20,
                'r': 0
            },
            transition={'duration': 0},
            showlegend=False,
            shapes=shape_list,
        ))

    #        figure_data['layout']['shapes'].extend(shape_list)

    return figure_data