Example #1
0
def plot_concept_evolution(
    scenarios,
    tree,
    fileformat='pdf',
    degree=90,
    **keywords
):
    """
    Plot the evolution according to the MLN method of all words for a given concept.
    
    Parameters
    ----------
    tree : str
        A tree representation in Newick format.
    fileformat : str (default="pdf")
        A valid fileformat according to Matplotlib.
    degree : int (default=90)
        The degree by which the tree is drawn. 360 yields a circular tree, 180
        yields a tree filling half of the space of a circle.
    """

    # make defaults
    defaults = dict(
        figsize=(15, 15),
        left=0.05,
        top=0.95,
        bottom=0.05,
        right=0.95,
        colormap=mpl.cm.jet,
        edgewidth=5,
        radius=2.5,
        outer_radius=0.5,
        inner_radius=0.25,
        cognates='',
        usetex=False,
        latex_preamble=False,
        textsize=8,
        change=lambda x: x ** 1.75,
        xlim=0,
        ylim=0,
        xlimr=False,
        xliml=False,
        ylimt=False,
        ylimb=False,
        rootsize=10,
        legend=True,
        legendsize=5,
        legendAloc='upper right',
        legendBloc='lower right',
        markeredgewidth=2.5,
        wedgeedgewidth=2,
        gain_linestyle='dotted',
        loss_linestyle='solid',
        ax_linewidth=0,
        labels={},
        _prefix='-   ',
        _suffix='   -',
        colors={},
        start=0,
        filename=rcParams['filename'],
        loss_alpha=0.1,
        loss_background='0.75',
        edges=[],
        hedge_color="black",
        hedge_width=5,
        hedge_linestyle='dashed',
    )
    keywords.update(defaults)

    # set filename as variable for convenience
    filename = keywords['filename']

    # XXX customize later XXX
    colormap = keywords['colormap']

    # switch backend, depending on whether tex is used or not
    backend = mpl.get_backend()
    if keywords['usetex'] and backend != 'pgf':
        plt.switch_backend('pgf')
    elif not keywords['usetex'] and backend != 'TkAgg':
        plt.switch_backend('TkAgg')

    # check for preamble settings
    if keywords['latex_preamble']:
        mpl.rcParams['pgf.preamble'] = keywords['latex_preamble']

    # make a graph
    graph = nx.Graph()

    # get the tgraph
    tgraph = radial_layout(
        tree,
        degree=degree,
        change=keywords['change'],
        start=keywords['start']
    )

    # get the taxa
    taxa = [n[0] for n in tgraph.nodes(data=True) if n[1]['tip']]

    # set the labels
    labels = {}
    for taxon in taxa:
        if taxon in keywords['labels']:
            labels[taxon] = keywords['labels'][taxon]
        else:
            labels[taxon] = taxon

    # get the number of paps in order to get the right colors
    cfunc = np.array(np.linspace(10, 256, len(scenarios)), dtype='int')

    if not keywords['colors']:
        colors = {scenarios[i][0]: mpl.colors.rgb2hex(colormap(cfunc[i]))
                  for i in range(len(scenarios))}
    else:
        colors = keywords['colors']

    # get the wedges for the paps
    wedges = {}
    linsp = np.linspace(0, 360, len(scenarios) + 1)
    for i, scenario in enumerate(scenarios):
        pap = scenario[0]
        theta1, theta2 = linsp[i], linsp[i + 1]
        wedges[pap] = (theta1, theta2)

    if keywords['legend']:

        # set the linestyle for the legend
        if keywords['gain_linestyle'] == 'dotted':
            ls = ':'
        elif keywords['gain_linestyle'] == 'dashed':
            ls = '--'

        legendEntriesA = []
        legendTextA = []

        # add stuff for the legend
        for pap, gls in scenarios:
            w = mpl.patches.Wedge(
                (0, 0),
                1,
                wedges[pap][0],
                wedges[pap][1],
                facecolor=colors[pap],
                zorder=1,
                linewidth=keywords['wedgeedgewidth'],
                edgecolor='black'
            )
            legendEntriesA += [w]
            legendTextA += [pap]

        # second legend explains evolution
        legendEntriesB = []
        legendTextB = []
        p = mpl.patches.Wedge(
            (0, 0),
            1,
            0,
            360,
            facecolor='0.5',
            linewidth=keywords['wedgeedgewidth'],
            edgecolor='black',
        )
        legendEntriesB += [p]
        legendTextB += ['Loss Event']
        p, = plt.plot(
            0, 0,
            ls,
            color='black',
            linewidth=keywords['wedgeedgewidth']
        )
        legendEntriesB += [p]
        legendTextB += ['Gain Event']

        # overwrite stuff
        plt.plot(0, 0, 'o', markersize=2, zorder=2, color='white')

    # iterate over the paps and append states to the graph
    for pap, gls in scenarios:

        # get the graph with the model
        g = gls2gml(
            gls,
            tgraph,
            tree,
            filename=''
        )

        # iterate over the graph
        for n, d in g.nodes(data=True):

            # add the node if necessary
            if n not in graph:
                graph.add_node(n)

            # add a pap-dictionary if it's not already there
            if 'pap' not in graph.node[n]:
                graph.node[n]['pap'] = {}

            # add data
            graph.node[n]['pap'][pap] = d['state']

    # create the figure
    fig = plt.figure(figsize=keywords['figsize'])
    figsp = fig.add_subplot(111)
    figsp.axes.get_xaxis().set_visible(False)
    figsp.axes.get_yaxis().set_visible(False)

    for s in figsp.spines.values():
        s.set_linewidth(keywords['ax_linewidth'])

    plt.axis('equal')

    xvals = []
    yvals = []

    # iterate over edges first
    for nA, nB in g.edges():
        gA = g.node[nA]['graphics']
        gB = g.node[nB]['graphics']
        xA, yA = gA['x'], gA['y']
        xB, yB = gB['x'], gB['y']

        plt.plot(
            [xA, xB],
            [yA, yB],
            '-',
            color='black',
            linewidth=keywords['edgewidth']
        )

    # add horizontal edges if this option is chosen
    if keywords['edges']:
        # get the coordinates
        for nA, nB in keywords['edges']:
            gA = g.node[nA]['graphics']
            gB = g.node[nB]['graphics']
            xA, yA = gA['x'], gA['y']
            xB, yB = gB['x'], gB['y']

            plt.plot(
                [xA, xB],
                [yA, yB],
                '-',
                color=keywords['hedge_color'],
                linewidth=keywords["hedge_width"],
                linestyle=keywords['hedge_linestyle']
            )

    # now iterate over the nodes
    for n, d in graph.nodes(data=True):
        cpaps = d['pap']
        x, y = g.node[n]['graphics']['x'], g.node[n]['graphics']['y']

        # get z-value which serves as zorder attribute
        try:
            z = 6 * len(tree.getConnectingEdges('root', n))
        except:
            z = 0

        xvals += [x]
        yvals += [y]

        # plot the default marker
        plt.plot(
            x,
            y,
            'o',
            markersize=keywords['rootsize'],
            color='black',
            zorder=50
        )
        # check for origins in cpaps
        if 'O' in cpaps.values():
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] + keywords['outer_radius'],
                0,
                360,
                facecolor='white',
                zorder=57 + z,
                linewidth=keywords['markeredgewidth'],
                linestyle=keywords['gain_linestyle'],
            )
            figsp.add_artist(w)
        # check for retentions
        elif 'o' in cpaps.values():
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] + keywords['outer_radius'],
                0,
                360,
                facecolor='white',
                zorder=56 + z,
                linewidth=keywords['markeredgewidth'],
                linestyle='solid',
            )
            figsp.add_artist(w)

        if 'L' in cpaps.values() and 'O' in cpaps.values():
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] + keywords['outer_radius'],
                0,
                360,
                facecolor=keywords['loss_background'],
                zorder=58 + z,
                linewidth=keywords['markeredgewidth'],
                edgecolor='black',
                linestyle=keywords['loss_linestyle']
            )
            figsp.add_artist(w)

        elif "L" in cpaps.values():
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] + keywords['outer_radius'],
                0,
                360,
                facecolor=keywords['loss_background'],
                zorder=59 + z,
                linewidth=keywords['markeredgewidth'],
                edgecolor='black',
            )
            figsp.add_artist(w)

        # plot all wedges
        for pap in cpaps:

            theta1, theta2 = wedges[pap]
            color = colors[pap]

            # check for characteristics of this pap

            # if it's a loss
            if cpaps[pap] == 'L':

                w = mpl.patches.Wedge(
                    (x, y),
                    keywords['radius'],
                    theta1,
                    theta2,
                    facecolor=color,
                    zorder=61 + z,
                    alpha=keywords['loss_alpha'],  # 0.25,
                    linewidth=keywords['wedgeedgewidth'],
                    edgecolor='black',
                    linestyle=keywords['loss_linestyle']
                )
                figsp.add_artist(w)

            elif cpaps[pap] == 'o':

                w = mpl.patches.Wedge(
                    (x, y),
                    keywords['radius'],
                    theta1,
                    theta2,
                    facecolor=color,
                    zorder=61 + z,
                    linewidth=keywords['wedgeedgewidth'],
                    edgecolor='black'
                )
                figsp.add_artist(w)

            elif cpaps[pap] == 'O':

                w = mpl.patches.Wedge(
                    (x, y),
                    keywords['radius'],
                    theta1,
                    theta2,
                    facecolor=color,
                    zorder=61 + z,
                    linewidth=keywords['wedgeedgewidth'],
                    edgecolor='black',
                    linestyle=keywords['gain_linestyle']
                )
                figsp.add_artist(w)

                # add the labels if this option is chosen
        if keywords['labels']:
            # if node is a tip
            if tgraph.node[n]['tip']:

                # get the values
                gf = tgraph.node[n]['graphics']
                r = gf['angle']
                x, y = gf['x'], gf['y']
                ha = gf['s']

                # modify the text
                if ha == 'left':
                    text = keywords['_prefix'] + labels[n]
                else:
                    text = labels[n] + keywords['_suffix']

                # plot the text
                plt.text(
                    x,
                    y,
                    text,
                    size=keywords['textsize'],
                    va='center',
                    ha=ha,
                    fontweight='bold',
                    color='black',
                    rotation=r,
                    rotation_mode='anchor',
                    zorder=z
                )

    # set up the xlimits
    if not keywords['xlimr'] and not keywords['xliml']:
        xl, xr = 2 * [keywords['xlim']]
    else:
        xl, xr = keywords['xliml'], keywords['xlimr']

    # set up the xlimits
    if not keywords['ylimt'] and not keywords['ylimb']:
        yb, yt = 2 * [keywords['ylim']]
    else:
        yb, yt = keywords['ylimb'], keywords['ylimt']

    plt.xlim((min(xvals) - xl, max(xvals) + xr))
    plt.ylim((min(yvals) - yb, max(yvals) + yt))

    prop = mpl.font_manager.FontProperties(size=keywords['legendsize'])

    if keywords['legend']:
        legend1 = plt.legend(
            legendEntriesA,
            legendTextA,
            loc=keywords['legendAloc'],
            numpoints=1,
            prop=prop
        )
        plt.legend(
            legendEntriesB,
            legendTextB,
            loc=keywords['legendBloc'],
            prop=prop
        )
        figsp.add_artist(legend1)

    plt.subplots_adjust(
        left=keywords['left'],
        right=keywords['right'],
        top=keywords['top'],
        bottom=keywords['bottom']
    )

    plt.savefig(filename + '.' + fileformat)
    plt.clf()
    log.file_written(filename + '.' + fileformat)
Example #2
0
def plot_gls(
    gls,
    treestring,
    degree=90,
    fileformat='pdf',
    **keywords
):
    """
    Plot a gain-loss scenario for a given reference tree.
    """

    # get kewyords
    defaults = dict(
        figsize=(15, 15),
        left=0.05,
        top=0.95,
        bottom=0.05,
        right=0.95,
        radius=0.5,
        textsize=8,
        edgewidth=5,
        linewidth=2,
        scale_radius=1.2,
        ylim=1,
        xlim=1,
        text=True,
        gain_color='white',
        loss_color='black',
        gain_linestyle='dotted',
        loss_linestyle='solid',
        ax_linewidth=0,
        filename=rcParams['filename']
    )

    for k in defaults:
        if k not in keywords:
            keywords[k] = defaults[k]

    # set filename as variabel for convenience
    filename = keywords['filename']

    try:
        tree = cg.LoadTree(treestring=treestring)
    except:
        try:
            tree = cg.LoadTree(treestring)
        except:
            tree = treestring

    tgraph = radial_layout(treestring, degree=degree)

    graph = gls2gml(
        gls,
        tgraph,
        tree
    )

    nodes = []

    # assign nodes and edges
    for n, d in graph.nodes(data=True):
        g = d['graphics']
        x = g['x']
        y = g['y']
        s = d['state']

        nodes += [(x, y, s)]

    # now plot the stuff
    fig = plt.figure(figsize=keywords['figsize'])
    figsp = fig.add_subplot(111)
    figsp.axes.get_xaxis().set_visible(False)
    figsp.axes.get_yaxis().set_visible(False)

    # set the axes linewidht
    for s in figsp.spines.values():
        s.set_linewidth(keywords['ax_linewidth'])

    plt.axis('equal')

    for nA, nB in graph.edges():
        xA = graph.node[nA]['graphics']['x']
        xB = graph.node[nB]['graphics']['x']
        yA = graph.node[nA]['graphics']['y']
        yB = graph.node[nB]['graphics']['y']

        plt.plot(
            [xA, xB],
            [yA, yB],
            '-',
            color='black',
            linewidth=keywords['edgewidth'],
            zorder=1
        )

    # now, iterate over nodes
    for x, y, s in nodes:
        if s == 'O':
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'],
                0, 360,
                facecolor=keywords['gain_color'],
                linewidth=keywords['linewidth'],
                linestyle=keywords['gain_linestyle']
            )
        elif s == 'o':
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] / keywords['scale_radius'],
                0, 360,
                facecolor=keywords['gain_color'],
                linewidth=keywords['linewidth']
            )
        elif s == 'L':
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'],
                0, 360,
                facecolor=keywords['loss_color'],
                linewidth=keywords['linewidth'],
                linestyle=keywords['loss_linestyle']
            )
        else:
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] / keywords['scale_radius'],
                0, 360,
                facecolor=keywords['loss_color'],
                linewidth=keywords['linewidth']
            )
        figsp.add_artist(w)

        # if text is chosen as argument
        if keywords['text']:
            if s in 'Oo':
                t = '1'
                c = 'black'
            else:
                t = '0'
                c = 'white'

            plt.text(
                x,
                y,
                t,
                size=keywords['textsize'],
                color=c,
                va="center",
                ha="center",
                fontweight='bold'
            )

    # set x and y-values
    xvals = [x[0] for x in nodes]
    yvals = [x[1] for x in nodes]

    plt.xlim(min(xvals) - keywords['xlim'], max(xvals) + keywords['xlim'])
    plt.ylim(min(yvals) - keywords['ylim'], max(yvals) + keywords['ylim'])

    plt.subplots_adjust(
        left=keywords['left'],
        right=keywords['right'],
        top=keywords['top'],
        bottom=keywords['bottom']
    )
    plt.savefig(
        filename + '.' + fileformat
    )
    plt.clf()
    log.file_written(filename + '.' + fileformat)
Example #3
0
def plot_tree(
    treestring,
    degree=90,
    fileformat='pdf',
    root="root",
    **keywords
):
    """
    Plot a Newick tree to PDF or other graphical formats.

    Parameters
    ----------
    treestring : str
        A string in Newick format.
    degree : int
        Determine the degree of the tree (this determines how "circular" the
        tree will be).
    fileformat : str (default="pdf")
        Select the fileformat to which the tree shall be written.
    filename : str
        Determine the name of the file to which the data shall be written.
        Defaults to a timestamp.
    figsize : tuple (default=(10,10))
        Determine the size of the figure.
    """

    default = dict(
        ax_linewidth=0,
        bg='black',
        bottom=0.05,
        change=lambda x: x ** 1.75,
        edge_list=[],
        figsize=(10, 10),
        filename=rcParams['filename'],
        fontweight='bold',
        frameon=False,
        ha='center',
        labels=[],
        left=0.05,
        linecolor='black',
        linewidth=5,
        no_labels=False,
        node_dict={},
        nodecolor='black',
        nodesize=10,
        right=0.95,
        start=0,
        textcolor='white',
        textsize='10',
        top=0.95,
        usetex=False,
        va='center',
        xlim=5,
        xliml=False,
        xlimr=False,
        ylim=5,
        ylimb=False,
        ylimt=False,
        rotation_mode='anchor',
        latex_preamble=False,
    )
    for k in default:
        if k not in keywords:
            keywords[k] = default[k]

    # set filename as variable for convenience
    filename = keywords['filename']

    # switch backend, depending on whether tex is used or not
    backend = mpl.get_backend()
    if keywords['usetex'] and backend != 'pgf':
        plt.switch_backend('pgf')
        mpl.rcParams['text.latex.unicode'] = True
    elif not keywords['usetex'] and backend != 'TkAgg':
        plt.switch_backend('TkAgg')

    if keywords['latex_preamble']:
        mpl.rcParams['pgf.preamble'] = keywords['latex_preamble']

    # get the tree-graph
    graph = radial_layout(
        treestring,
        degree=degree,
        change=keywords['change'],
        start=keywords['start'],
        root=root
    )

    # create the figure
    fig = plt.figure(figsize=keywords['figsize'])
    figsp = fig.add_subplot(111)
    figsp.axes.get_xaxis().set_visible(False)
    figsp.axes.get_yaxis().set_visible(False)

    for s in figsp.spines.values():
        s.set_linewidth(keywords['ax_linewidth'])

    # plt.axes(frameon=keywords['frameon'])
    plt.axis('equal')
    plt.xticks([])
    plt.yticks([])

    # get xlim and ylim
    xvals, yvals = [], []
    # start iterating over edges
    for nA, nB, d in list(graph.edges(data=True)) + keywords['edge_list']:

        # get the coordinates
        xA = graph.node[nA]['graphics']['x']
        yA = graph.node[nA]['graphics']['y']
        xB = graph.node[nB]['graphics']['x']
        yB = graph.node[nB]['graphics']['y']

        if 'color' in d:
            plt.plot(
                [xA, xB],
                [yA, yB],
                '-',
                **d
            )
        else:
            plt.plot(
                [xA, xB],
                [yA, yB],
                '-',
                color=keywords['linecolor'],
                linewidth=keywords['linewidth'],
            )

    # get the nodes
    for n, d in graph.nodes(data=True):

        g = d['graphics']
        x, y = g['x'], g['y']

        xvals += [x]
        yvals += [y]

        # try to get information from the node-dict
        try:
            settings = {}
            settings.update(keywords['node_dict'][n])
        except:
            settings = {}

        # overwrite the stuff in keywords
        for k in keywords:
            if k not in settings:
                settings[k] = keywords[k]

        if d['label'].startswith('edge') \
                or d['label'].startswith(root) or keywords['no_labels']:
            plt.plot(
                x,
                y,
                'o',
                markersize=settings['nodesize'],
                color=settings['nodecolor'],
                markeredgewidth=settings['linewidth']
            )
        else:
            try:
                label = keywords['labels'][d['label']]
            except:
                label = d['label']
            if 'rotation' in settings:
                r = settings['rotation']
            else:
                r = g['angle']
            plt.text(
                x,
                y,
                label,
                # d['label'],
                color=settings['textcolor'],
                fontweight=settings['fontweight'],
                va=settings['va'],
                ha=g['s'],
                bbox=dict(
                    facecolor=settings['bg'],
                    boxstyle='square,pad=0.2',
                    ec="none",
                ),
                size=settings['textsize'],
                rotation=r,  # g['angle'],
                rotation_mode=settings['rotation_mode']
            )

    # set up the xlimits
    if not keywords['xlimr'] and not keywords['xliml']:
        xl, xr = 2 * [keywords['xlim']]
    else:
        xl, xr = keywords['xliml'], keywords['xlimr']

    # set up the xlimits
    if not keywords['ylimt'] and not keywords['ylimb']:
        yb, yt = 2 * [keywords['ylim']]
    else:
        yb, yt = keywords['ylimb'], keywords['ylimt']

    plt.xlim((min(xvals) - xl, max(xvals) + xr))
    plt.ylim((min(yvals) - yb, max(yvals) + yt))

    plt.subplots_adjust(
        left=keywords['left'],
        right=keywords['right'],
        top=keywords['top'],
        bottom=keywords['bottom']
    )

    plt.savefig(filename + '.' + fileformat)
    plt.clf()
    log.file_written(filename + '.' + fileformat)
Example #4
0
def plot_concept_evolution(scenarios,
                           tree,
                           fileformat='pdf',
                           degree=90,
                           **keywords):
    """
    Plot the evolution according to the MLN method of all words for a given concept.
    
    Parameters
    ----------
    tree : str
        A tree representation in Newick format.
    fileformat : str (default="pdf")
        A valid fileformat according to Matplotlib.
    degree : int (default=90)
        The degree by which the tree is drawn. 360 yields a circular tree, 180
        yields a tree filling half of the space of a circle.
    """

    # make defaults
    defaults = dict(
        figsize=(15, 15),
        left=0.05,
        top=0.95,
        bottom=0.05,
        right=0.95,
        colormap=mpl.cm.jet,
        edgewidth=5,
        radius=2.5,
        outer_radius=0.5,
        inner_radius=0.25,
        cognates='',
        usetex=False,
        latex_preamble=False,
        textsize=8,
        change=lambda x: x**1.75,
        xlim=0,
        ylim=0,
        xlimr=False,
        xliml=False,
        ylimt=False,
        ylimb=False,
        rootsize=10,
        legend=True,
        legendsize=5,
        legendAloc='upper right',
        legendBloc='lower right',
        markeredgewidth=2.5,
        wedgeedgewidth=2,
        gain_linestyle='dotted',
        loss_linestyle='solid',
        ax_linewidth=0,
        labels={},
        _prefix='-   ',
        _suffix='   -',
        colors={},
        start=0,
        filename=rcParams['filename'],
        loss_alpha=0.1,
        loss_background='0.75',
        edges=[],
        hedge_color="black",
        hedge_width=5,
        hedge_linestyle='dashed',
    )
    keywords.update(defaults)

    # set filename as variable for convenience
    filename = keywords['filename']

    # XXX customize later XXX
    colormap = keywords['colormap']

    # switch backend, depending on whether tex is used or not
    backend = mpl.get_backend()
    if keywords['usetex'] and backend != 'pgf':
        plt.switch_backend('pgf')
    elif not keywords['usetex'] and backend != 'TkAgg':
        plt.switch_backend('TkAgg')

    # check for preamble settings
    if keywords['latex_preamble']:
        mpl.rcParams['pgf.preamble'] = keywords['latex_preamble']

    # make a graph
    graph = nx.Graph()

    # get the tgraph
    tgraph = radial_layout(tree,
                           degree=degree,
                           change=keywords['change'],
                           start=keywords['start'])

    # get the taxa
    taxa = [n[0] for n in tgraph.nodes(data=True) if n[1]['tip']]

    # set the labels
    labels = {}
    for taxon in taxa:
        if taxon in keywords['labels']:
            labels[taxon] = keywords['labels'][taxon]
        else:
            labels[taxon] = taxon

    # get the number of paps in order to get the right colors
    cfunc = np.array(np.linspace(10, 256, len(scenarios)), dtype='int')

    if not keywords['colors']:
        colors = {
            scenarios[i][0]: mpl.colors.rgb2hex(colormap(cfunc[i]))
            for i in range(len(scenarios))
        }
    else:
        colors = keywords['colors']

    # get the wedges for the paps
    wedges = {}
    linsp = np.linspace(0, 360, len(scenarios) + 1)
    for i, scenario in enumerate(scenarios):
        pap = scenario[0]
        theta1, theta2 = linsp[i], linsp[i + 1]
        wedges[pap] = (theta1, theta2)

    if keywords['legend']:

        # set the linestyle for the legend
        if keywords['gain_linestyle'] == 'dotted':
            ls = ':'
        elif keywords['gain_linestyle'] == 'dashed':
            ls = '--'

        legendEntriesA = []
        legendTextA = []

        # add stuff for the legend
        for pap, gls in scenarios:
            w = mpl.patches.Wedge((0, 0),
                                  1,
                                  wedges[pap][0],
                                  wedges[pap][1],
                                  facecolor=colors[pap],
                                  zorder=1,
                                  linewidth=keywords['wedgeedgewidth'],
                                  edgecolor='black')
            legendEntriesA += [w]
            legendTextA += [pap]

        # second legend explains evolution
        legendEntriesB = []
        legendTextB = []
        p = mpl.patches.Wedge(
            (0, 0),
            1,
            0,
            360,
            facecolor='0.5',
            linewidth=keywords['wedgeedgewidth'],
            edgecolor='black',
        )
        legendEntriesB += [p]
        legendTextB += ['Loss Event']
        p, = plt.plot(0,
                      0,
                      ls,
                      color='black',
                      linewidth=keywords['wedgeedgewidth'])
        legendEntriesB += [p]
        legendTextB += ['Gain Event']

        # overwrite stuff
        plt.plot(0, 0, 'o', markersize=2, zorder=2, color='white')

    # iterate over the paps and append states to the graph
    for pap, gls in scenarios:

        # get the graph with the model
        g = gls2gml(gls, tgraph, tree, filename='')

        # iterate over the graph
        for n, d in g.nodes(data=True):

            # add the node if necessary
            if n not in graph:
                graph.add_node(n)

            # add a pap-dictionary if it's not already there
            if 'pap' not in graph.node[n]:
                graph.node[n]['pap'] = {}

            # add data
            graph.node[n]['pap'][pap] = d['state']

    # create the figure
    fig = plt.figure(figsize=keywords['figsize'])
    figsp = fig.add_subplot(111)
    figsp.axes.get_xaxis().set_visible(False)
    figsp.axes.get_yaxis().set_visible(False)

    for s in figsp.spines.values():
        s.set_linewidth(keywords['ax_linewidth'])

    plt.axis('equal')

    xvals = []
    yvals = []

    # iterate over edges first
    for nA, nB in g.edges():
        gA = g.node[nA]['graphics']
        gB = g.node[nB]['graphics']
        xA, yA = gA['x'], gA['y']
        xB, yB = gB['x'], gB['y']

        plt.plot([xA, xB], [yA, yB],
                 '-',
                 color='black',
                 linewidth=keywords['edgewidth'])

    # add horizontal edges if this option is chosen
    if keywords['edges']:
        # get the coordinates
        for nA, nB in keywords['edges']:
            gA = g.node[nA]['graphics']
            gB = g.node[nB]['graphics']
            xA, yA = gA['x'], gA['y']
            xB, yB = gB['x'], gB['y']

            plt.plot([xA, xB], [yA, yB],
                     '-',
                     color=keywords['hedge_color'],
                     linewidth=keywords["hedge_width"],
                     linestyle=keywords['hedge_linestyle'])

    # now iterate over the nodes
    for n, d in graph.nodes(data=True):
        cpaps = d['pap']
        x, y = g.node[n]['graphics']['x'], g.node[n]['graphics']['y']

        # get z-value which serves as zorder attribute
        try:
            z = 6 * len(tree.getConnectingEdges('root', n))
        except:
            z = 0

        xvals += [x]
        yvals += [y]

        # plot the default marker
        plt.plot(x,
                 y,
                 'o',
                 markersize=keywords['rootsize'],
                 color='black',
                 zorder=50)
        # check for origins in cpaps
        if 'O' in cpaps.values():
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] + keywords['outer_radius'],
                0,
                360,
                facecolor='white',
                zorder=57 + z,
                linewidth=keywords['markeredgewidth'],
                linestyle=keywords['gain_linestyle'],
            )
            figsp.add_artist(w)
        # check for retentions
        elif 'o' in cpaps.values():
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] + keywords['outer_radius'],
                0,
                360,
                facecolor='white',
                zorder=56 + z,
                linewidth=keywords['markeredgewidth'],
                linestyle='solid',
            )
            figsp.add_artist(w)

        if 'L' in cpaps.values() and 'O' in cpaps.values():
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] + keywords['outer_radius'],
                0,
                360,
                facecolor=keywords['loss_background'],
                zorder=58 + z,
                linewidth=keywords['markeredgewidth'],
                edgecolor='black',
                linestyle=keywords['loss_linestyle'])
            figsp.add_artist(w)

        elif "L" in cpaps.values():
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] + keywords['outer_radius'],
                0,
                360,
                facecolor=keywords['loss_background'],
                zorder=59 + z,
                linewidth=keywords['markeredgewidth'],
                edgecolor='black',
            )
            figsp.add_artist(w)

        # plot all wedges
        for pap in cpaps:

            theta1, theta2 = wedges[pap]
            color = colors[pap]

            # check for characteristics of this pap

            # if it's a loss
            if cpaps[pap] == 'L':

                w = mpl.patches.Wedge(
                    (x, y),
                    keywords['radius'],
                    theta1,
                    theta2,
                    facecolor=color,
                    zorder=61 + z,
                    alpha=keywords['loss_alpha'],  # 0.25,
                    linewidth=keywords['wedgeedgewidth'],
                    edgecolor='black',
                    linestyle=keywords['loss_linestyle'])
                figsp.add_artist(w)

            elif cpaps[pap] == 'o':

                w = mpl.patches.Wedge((x, y),
                                      keywords['radius'],
                                      theta1,
                                      theta2,
                                      facecolor=color,
                                      zorder=61 + z,
                                      linewidth=keywords['wedgeedgewidth'],
                                      edgecolor='black')
                figsp.add_artist(w)

            elif cpaps[pap] == 'O':

                w = mpl.patches.Wedge((x, y),
                                      keywords['radius'],
                                      theta1,
                                      theta2,
                                      facecolor=color,
                                      zorder=61 + z,
                                      linewidth=keywords['wedgeedgewidth'],
                                      edgecolor='black',
                                      linestyle=keywords['gain_linestyle'])
                figsp.add_artist(w)

                # add the labels if this option is chosen
        if keywords['labels']:
            # if node is a tip
            if tgraph.node[n]['tip']:

                # get the values
                gf = tgraph.node[n]['graphics']
                r = gf['angle']
                x, y = gf['x'], gf['y']
                ha = gf['s']

                # modify the text
                if ha == 'left':
                    text = keywords['_prefix'] + labels[n]
                else:
                    text = labels[n] + keywords['_suffix']

                # plot the text
                plt.text(x,
                         y,
                         text,
                         size=keywords['textsize'],
                         va='center',
                         ha=ha,
                         fontweight='bold',
                         color='black',
                         rotation=r,
                         rotation_mode='anchor',
                         zorder=z)

    # set up the xlimits
    if not keywords['xlimr'] and not keywords['xliml']:
        xl, xr = 2 * [keywords['xlim']]
    else:
        xl, xr = keywords['xliml'], keywords['xlimr']

    # set up the xlimits
    if not keywords['ylimt'] and not keywords['ylimb']:
        yb, yt = 2 * [keywords['ylim']]
    else:
        yb, yt = keywords['ylimb'], keywords['ylimt']

    plt.xlim((min(xvals) - xl, max(xvals) + xr))
    plt.ylim((min(yvals) - yb, max(yvals) + yt))

    prop = mpl.font_manager.FontProperties(size=keywords['legendsize'])

    if keywords['legend']:
        legend1 = plt.legend(legendEntriesA,
                             legendTextA,
                             loc=keywords['legendAloc'],
                             numpoints=1,
                             prop=prop)
        plt.legend(legendEntriesB,
                   legendTextB,
                   loc=keywords['legendBloc'],
                   prop=prop)
        figsp.add_artist(legend1)

    plt.subplots_adjust(left=keywords['left'],
                        right=keywords['right'],
                        top=keywords['top'],
                        bottom=keywords['bottom'])

    plt.savefig(filename + '.' + fileformat)
    plt.clf()
    log.file_written(filename + '.' + fileformat)
Example #5
0
def plot_gls(gls, treestring, degree=90, fileformat='pdf', **keywords):
    """
    Plot a gain-loss scenario for a given reference tree.
    """

    # get kewyords
    defaults = dict(figsize=(15, 15),
                    left=0.05,
                    top=0.95,
                    bottom=0.05,
                    right=0.95,
                    radius=0.5,
                    textsize=8,
                    edgewidth=5,
                    linewidth=2,
                    scale_radius=1.2,
                    ylim=1,
                    xlim=1,
                    text=True,
                    gain_color='white',
                    loss_color='black',
                    gain_linestyle='dotted',
                    loss_linestyle='solid',
                    ax_linewidth=0,
                    filename=rcParams['filename'])

    for k in defaults:
        if k not in keywords:
            keywords[k] = defaults[k]

    # set filename as variabel for convenience
    filename = keywords['filename']

    try:
        tree = cg.LoadTree(treestring=treestring)
    except:
        try:
            tree = cg.LoadTree(treestring)
        except:
            tree = treestring

    tgraph = radial_layout(treestring, degree=degree)

    graph = gls2gml(gls, tgraph, tree)

    nodes = []

    # assign nodes and edges
    for n, d in graph.nodes(data=True):
        g = d['graphics']
        x = g['x']
        y = g['y']
        s = d['state']

        nodes += [(x, y, s)]

    # now plot the stuff
    fig = plt.figure(figsize=keywords['figsize'])
    figsp = fig.add_subplot(111)
    figsp.axes.get_xaxis().set_visible(False)
    figsp.axes.get_yaxis().set_visible(False)

    # set the axes linewidht
    for s in figsp.spines.values():
        s.set_linewidth(keywords['ax_linewidth'])

    plt.axis('equal')

    for nA, nB in graph.edges():
        xA = graph.node[nA]['graphics']['x']
        xB = graph.node[nB]['graphics']['x']
        yA = graph.node[nA]['graphics']['y']
        yB = graph.node[nB]['graphics']['y']

        plt.plot([xA, xB], [yA, yB],
                 '-',
                 color='black',
                 linewidth=keywords['edgewidth'],
                 zorder=1)

    # now, iterate over nodes
    for x, y, s in nodes:
        if s == 'O':
            w = mpl.patches.Wedge((x, y),
                                  keywords['radius'],
                                  0,
                                  360,
                                  facecolor=keywords['gain_color'],
                                  linewidth=keywords['linewidth'],
                                  linestyle=keywords['gain_linestyle'])
        elif s == 'o':
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] / keywords['scale_radius'],
                0,
                360,
                facecolor=keywords['gain_color'],
                linewidth=keywords['linewidth'])
        elif s == 'L':
            w = mpl.patches.Wedge((x, y),
                                  keywords['radius'],
                                  0,
                                  360,
                                  facecolor=keywords['loss_color'],
                                  linewidth=keywords['linewidth'],
                                  linestyle=keywords['loss_linestyle'])
        else:
            w = mpl.patches.Wedge(
                (x, y),
                keywords['radius'] / keywords['scale_radius'],
                0,
                360,
                facecolor=keywords['loss_color'],
                linewidth=keywords['linewidth'])
        figsp.add_artist(w)

        # if text is chosen as argument
        if keywords['text']:
            if s in 'Oo':
                t = '1'
                c = 'black'
            else:
                t = '0'
                c = 'white'

            plt.text(x,
                     y,
                     t,
                     size=keywords['textsize'],
                     color=c,
                     va="center",
                     ha="center",
                     fontweight='bold')

    # set x and y-values
    xvals = [x[0] for x in nodes]
    yvals = [x[1] for x in nodes]

    plt.xlim(min(xvals) - keywords['xlim'], max(xvals) + keywords['xlim'])
    plt.ylim(min(yvals) - keywords['ylim'], max(yvals) + keywords['ylim'])

    plt.subplots_adjust(left=keywords['left'],
                        right=keywords['right'],
                        top=keywords['top'],
                        bottom=keywords['bottom'])
    plt.savefig(filename + '.' + fileformat)
    plt.clf()
    log.file_written(filename + '.' + fileformat)
Example #6
0
def plot_tree(treestring,
              degree=90,
              fileformat='pdf',
              root="root",
              **keywords):
    """
    Plot a Newick tree to PDF or other graphical formats.

    Parameters
    ----------
    treestring : str
        A string in Newick format.
    degree : int
        Determine the degree of the tree (this determines how "circular" the
        tree will be).
    fileformat : str (default="pdf")
        Select the fileformat to which the tree shall be written.
    filename : str
        Determine the name of the file to which the data shall be written.
        Defaults to a timestamp.
    figsize : tuple (default=(10,10))
        Determine the size of the figure.
    """

    default = dict(
        ax_linewidth=0,
        bg='black',
        bottom=0.05,
        change=lambda x: x**1.75,
        edge_list=[],
        figsize=(10, 10),
        filename=rcParams['filename'],
        fontweight='bold',
        frameon=False,
        ha='center',
        labels=[],
        left=0.05,
        linecolor='black',
        linewidth=5,
        no_labels=False,
        node_dict={},
        nodecolor='black',
        nodesize=10,
        right=0.95,
        start=0,
        textcolor='white',
        textsize='10',
        top=0.95,
        usetex=False,
        va='center',
        xlim=5,
        xliml=False,
        xlimr=False,
        ylim=5,
        ylimb=False,
        ylimt=False,
        rotation_mode='anchor',
        latex_preamble=False,
    )
    for k in default:
        if k not in keywords:
            keywords[k] = default[k]

    # set filename as variable for convenience
    filename = keywords['filename']

    # switch backend, depending on whether tex is used or not
    backend = mpl.get_backend()
    if keywords['usetex'] and backend != 'pgf':
        plt.switch_backend('pgf')
        mpl.rcParams['text.latex.unicode'] = True
    elif not keywords['usetex'] and backend != 'TkAgg':
        plt.switch_backend('TkAgg')

    if keywords['latex_preamble']:
        mpl.rcParams['pgf.preamble'] = keywords['latex_preamble']

    # get the tree-graph
    graph = radial_layout(treestring,
                          degree=degree,
                          change=keywords['change'],
                          start=keywords['start'],
                          root=root)

    # create the figure
    fig = plt.figure(figsize=keywords['figsize'])
    figsp = fig.add_subplot(111)
    figsp.axes.get_xaxis().set_visible(False)
    figsp.axes.get_yaxis().set_visible(False)

    for s in figsp.spines.values():
        s.set_linewidth(keywords['ax_linewidth'])

    # plt.axes(frameon=keywords['frameon'])
    plt.axis('equal')
    plt.xticks([])
    plt.yticks([])

    # get xlim and ylim
    xvals, yvals = [], []
    # start iterating over edges
    for nA, nB, d in list(graph.edges(data=True)) + keywords['edge_list']:

        # get the coordinates
        xA = graph.node[nA]['graphics']['x']
        yA = graph.node[nA]['graphics']['y']
        xB = graph.node[nB]['graphics']['x']
        yB = graph.node[nB]['graphics']['y']

        if 'color' in d:
            plt.plot([xA, xB], [yA, yB], '-', **d)
        else:
            plt.plot(
                [xA, xB],
                [yA, yB],
                '-',
                color=keywords['linecolor'],
                linewidth=keywords['linewidth'],
            )

    # get the nodes
    for n, d in graph.nodes(data=True):

        g = d['graphics']
        x, y = g['x'], g['y']

        xvals += [x]
        yvals += [y]

        # try to get information from the node-dict
        try:
            settings = {}
            settings.update(keywords['node_dict'][n])
        except:
            settings = {}

        # overwrite the stuff in keywords
        for k in keywords:
            if k not in settings:
                settings[k] = keywords[k]

        if d['label'].startswith('edge') \
                or d['label'].startswith(root) or keywords['no_labels']:
            plt.plot(x,
                     y,
                     'o',
                     markersize=settings['nodesize'],
                     color=settings['nodecolor'],
                     markeredgewidth=settings['linewidth'])
        else:
            try:
                label = keywords['labels'][d['label']]
            except:
                label = d['label']
            if 'rotation' in settings:
                r = settings['rotation']
            else:
                r = g['angle']
            plt.text(
                x,
                y,
                label,
                # d['label'],
                color=settings['textcolor'],
                fontweight=settings['fontweight'],
                va=settings['va'],
                ha=g['s'],
                bbox=dict(
                    facecolor=settings['bg'],
                    boxstyle='square,pad=0.2',
                    ec="none",
                ),
                size=settings['textsize'],
                rotation=r,  # g['angle'],
                rotation_mode=settings['rotation_mode'])

    # set up the xlimits
    if not keywords['xlimr'] and not keywords['xliml']:
        xl, xr = 2 * [keywords['xlim']]
    else:
        xl, xr = keywords['xliml'], keywords['xlimr']

    # set up the xlimits
    if not keywords['ylimt'] and not keywords['ylimb']:
        yb, yt = 2 * [keywords['ylim']]
    else:
        yb, yt = keywords['ylimb'], keywords['ylimt']

    plt.xlim((min(xvals) - xl, max(xvals) + xr))
    plt.ylim((min(yvals) - yb, max(yvals) + yt))

    plt.subplots_adjust(left=keywords['left'],
                        right=keywords['right'],
                        top=keywords['top'],
                        bottom=keywords['bottom'])

    plt.savefig(filename + '.' + fileformat)
    plt.clf()
    log.file_written(filename + '.' + fileformat)