def layout(node):
     if node.is_leaf():
         N = AttrFace("name", fgcolor="black")
         faces.add_face_to_node(N, node, 0)
     if "weight" in node.features:
         # Creates a sphere face whose size is proportional to node's
         # feature 1/gini index
         circle_face = CircleFace(radius=node.weight,
                                  color="RoyalBlue",
                                  style="sphere")
         circle_face.hz_align = 2
         circle_face.opacity = 0.3
         text_face = TextFace(text=node.name)
         faces.add_face_to_node(circle_face, node, 0, position="float")
         faces.add_face_to_node(text_face, node, 0, position="float")
 def my_layout(node):
     circle_color = 'lightgray' if colormap is None or node.name not in colormap else colormap[
         node.name]
     text_color = 'black'
     if isinstance(circle_color, str):
         C = CircleFace(radius=max(3, 10 * scipy.sqrt(node.frequency)),
                        color=circle_color,
                        label={
                            'text': str(node.frequency),
                            'color': text_color
                        } if node.frequency > 0 else None)
         C.rotation = -90
         C.hz_align = 1
         faces.add_face_to_node(C, node, 0)
     else:
         P = PieChartFace(
             [100 * x / node.frequency for x in circle_color.values()],
             2 * 10 * scipy.sqrt(node.frequency),
             2 * 10 * scipy.sqrt(node.frequency),
             colors=[(color if color != 'None' else 'lightgray')
                     for color in list(circle_color.keys())],
             line_color=None)
         T = TextFace(' '.join(
             [str(x) for x in list(circle_color.values())]),
                      tight_text=True)
         T.hz_align = 1
         T.rotation = -90
         faces.add_face_to_node(P, node, 0, position='branch-right')
         faces.add_face_to_node(T, node, 1, position='branch-right')
     if idlabel:
         T = TextFace(node.name, tight_text=True, fsize=6)
         T.rotation = -90
         T.hz_align = 1
         faces.add_face_to_node(
             T,
             node,
             1 if isinstance(circle_color, str) else 2,
             position='branch-right')
Example #3
0
def generateFigure(PF, sample, rank, input_file, output_base_name, file_type, plot_l1, scaling, output_dpi):

    # Make the ETE3 tree
    try:
        tree = ncbi.get_topology(PF.get_all_tax_ids(sample), rank_limit=rank)

    except:
        logging.getLogger('Tampa').critical("Input format not compatible.")
        exit(1)

    ts = TreeStyle()
    ts.layout_fn = PF.layout
    ts.mode = "c"
    ts.show_leaf_name = False
    ts.show_branch_length = False
    ts.show_branch_support = False
    ts.min_leaf_separation = 10
    ts.arc_span = 360
    #ts.legend.add_face(CircleFace(100, "#1b9e77", label="Predicted"), column=0)
    #ts.legend.add_face(CircleFace(100, '#d95f02', label="True"), column=1)
    # add white space to move the legend closer
    ts.legend.add_face(CircleFace(65, "#FFFFFF"), column=2)
    ts.legend.add_face(CircleFace(65, "#FFFFFF"), column=1)
    ts.legend.add_face(CircleFace(65, "#FFFFFF"), column=0)
    ts.legend.add_face(CircleFace(65, "#FFFFFF"), column=2)
    ts.legend.add_face(CircleFace(65, "#FFFFFF"), column=1)
    ts.legend.add_face(CircleFace(65, "#FFFFFF"), column=0)

    # add the legend
    legend_fs = 50
    C1 = CircleFace(100, "#1b9e77")
    C1.hz_align = True
    ts.legend.add_face(C1, column=0)
    T1 = TextFace("Predicted", fsize=legend_fs)
    T1.hz_align = True
    ts.legend.add_face(T1, column=0)

    if len(PF.ground_truth_dict) > 0:
        C2 = CircleFace(100, "#d95f02")
        C2.hz_align = True
        ts.legend.add_face(C2, column=1)
        T2 = TextFace("True", fsize=legend_fs)
        T2.hz_align = True
        ts.legend.add_face(T2, column=1)

    T3 = TextFace(f"Tool: {os.path.basename(input_file).split('.')[0]}", fsize=legend_fs)
    T3.hz_align = True
    ts.legend.add_face(T3, column=0)
    ts.allow_face_overlap = False  # this lets me mess a bit with font size and face size without the interaction of the two
    ts.min_leaf_separation = 10
    tree_output_file = f"{output_base_name}_tree_{rank}_{sample}.{file_type}"
    tree.render(tree_output_file, h=5.2, w=5, tree_style=ts, units="in", dpi=output_dpi)


    if plot_l1:

        # if you asked for L1 too, then plot that
        true_abundance_at_rank = []
        predicted_abundance_at_rank = []
        for node in tree.get_leaves():
            if node.rank == rank:
                tax_id = str(node.taxid)
                if tax_id in PF.ground_truth_tax_id_to_percentage:
                    true_abundance_at_rank.append(PF.ground_truth_tax_id_to_percentage[str(node.taxid)] / 100.)
                else:
                    true_abundance_at_rank.append(0)
                if tax_id in PF.profile_tax_id_to_percentage:
                    predicted_abundance_at_rank.append(PF.profile_tax_id_to_percentage[str(node.taxid)] / 100.)
                else:
                    predicted_abundance_at_rank.append(0)

        data = np.zeros((len(true_abundance_at_rank), 2))
        data[:, 0] = np.array(true_abundance_at_rank)
        data[:, 1] = np.array(predicted_abundance_at_rank)

        df = pd.DataFrame(data, columns=['True', 'Predicted'])
        # g = seaborn.FacetGrid(df, height=6)
        ax = seaborn.scatterplot(x='True', y='Predicted', data=df, color='b', s=55)
        eps = 1
        ax.set_aspect('equal')
        max_val = np.max(data) + eps
        ax.set_xlim(-.5, max_val)
        ax.set_ylim(-.5, max_val)
        ax.set_xbound(-.5, max_val)
        ax.set_ybound(-.5, max_val)

        #plt.figure(figsize=(6,6))
        plt.plot(np.linspace(0, max_val, 100), np.linspace(0, max_val, 100), color='k')

        for (x, y) in zip(true_abundance_at_rank, predicted_abundance_at_rank):
            if x > y:
                ax.vlines(x, y, x, colors='r')
            if y > x:
                ax.vlines(x, x, y, colors='r')
        plt.title(f"Tool: {os.path.basename(input_file).split('.')[0]}")
        plt.tight_layout()
        l1_out_file = f"{output_base_name}_L1_{rank}.{file_type}"
        plt.savefig(l1_out_file, dpi=output_dpi)
Example #4
0
 def my_layout(node):
     circle_color = 'lightgray' if colormap is None or node.name not in colormap else colormap[
         node.name]
     text_color = 'black'
     if isinstance(circle_color, str):
         if isolabel and hasattr(node, 'isotype'):
             nl = ''.join(
                 sorted(set([ISO_SHORT[iss] for iss in node.isotype]),
                        key=lambda x: ISO_TYPE_charORDER[x]))
         else:
             nl = str(node.frequency)
         C = CircleFace(radius=max(3, 10 * scipy.sqrt(node.frequency)),
                        color=circle_color,
                        label={
                            'text': nl,
                            'color': text_color
                        } if node.frequency > 0 else None)
         C.rotation = -90
         C.hz_align = 1
         faces.add_face_to_node(C, node, 0)
     else:
         P = PieChartFace(
             [100 * x / node.frequency for x in circle_color.values()],
             2 * 10 * scipy.sqrt(node.frequency),
             2 * 10 * scipy.sqrt(node.frequency),
             colors=[(color if color != 'None' else 'lightgray')
                     for color in list(circle_color.keys())],
             line_color=None)
         T = TextFace(' '.join(
             [str(x) for x in list(circle_color.values())]),
                      tight_text=True)
         T.hz_align = 1
         T.rotation = -90
         faces.add_face_to_node(P, node, 0, position='branch-right')
         faces.add_face_to_node(T, node, 1, position='branch-right')
     if idlabel:
         T = TextFace(node.name, tight_text=True, fsize=6)
         T.rotation = -90
         T.hz_align = 1
         faces.add_face_to_node(
             T,
             node,
             1 if isinstance(circle_color, str) else 2,
             position='branch-right')
     elif isolabel and hasattr(node, 'isotype') and False:
         iso_name = ''.join(
             sorted(set([ISO_SHORT[iss] for iss in node.isotype]),
                    key=lambda x: ISO_TYPE_charORDER[x]))
         #T = TextFace(iso_name, tight_text=True, fsize=6)
         #T.rotation = -90
         #T.hz_align = 1
         #faces.add_face_to_node(T, node, 1 if isinstance(circle_color, str) else 2, position='branch-right')
         C = CircleFace(radius=max(3, 10 * scipy.sqrt(node.frequency)),
                        color=circle_color,
                        label={
                            'text': iso_name,
                            'color': text_color
                        } if node.frequency > 0 else None)
         C.rotation = -90
         C.hz_align = 1
         faces.add_face_to_node(C, node, 0)