Exemple #1
0
def test_clipped_to_axes():
    # Ensure that _fully_clipped_to_axes() returns True under default
    # conditions for all projection types. Axes.get_tightbbox()
    # uses this to skip artists in layout calculations.
    arr = np.arange(100).reshape((10, 10))
    fig = plt.figure(figsize=(6, 2))
    ax1 = fig.add_subplot(131, projection='rectilinear')
    ax2 = fig.add_subplot(132, projection='mollweide')
    ax3 = fig.add_subplot(133, projection='polar')
    for ax in (ax1, ax2, ax3):
        # Default conditions (clipped by ax.bbox or ax.patch)
        ax.grid(False)
        h, = ax.plot(arr[:, 0])
        m = ax.pcolor(arr)
        assert h._fully_clipped_to_axes()
        assert m._fully_clipped_to_axes()
        # Non-default conditions (not clipped by ax.patch)
        rect = Rectangle((0, 0), 0.5, 0.5, transform=ax.transAxes)
        h.set_clip_path(rect)
        m.set_clip_path(rect.get_path(), rect.get_transform())
        assert not h._fully_clipped_to_axes()
        assert not m._fully_clipped_to_axes()
Exemple #2
0
            def add_legend_item(label, col, cur_x, cur_y, is_first, is_mut):
                legend_item_width = background_lengths[
                    0] + gap_handle_to_text + abs(
                        _get_text_bbox(label, ax, scale=ax_scale).width)
                if cur_x + legend_item_width > ax_xlim[1] and not is_first:
                    cur_x = pad_x
                    cur_y += line_height + line_height / 2.0
                p = Rectangle((cur_x, cur_y),
                              *background_lengths,
                              color=col,
                              lw=0)
                #p = Rectangle((0, 0), 1, 1, color=col)
                #p.set_transform(Affine2D().scale(*background_lengths).translate(cur_x, cur_y))
                legend_patches.append(p)
                if is_mut:
                    if label in legend_mut_to_patch:
                        p, w, h, pc_kwargs = legend_mut_to_patch[label]
                        #p.set_transform(p.get_transform() + Affine2D().scale(w, -h).translate(cur_x, cur_y + 0.5 + h * 0.5))
                        p.set_transform(
                            p.get_transform() +
                            Affine2D().scale(w, -h).translate(
                                *background_lengths * 0.5 +
                                (cur_x - 0.5 * w, cur_y + 0.5 * h)))
                        legend_pcs.append(PatchCollection([p], **pc_kwargs))
                    elif label in legend_mut_to_scatter:
                        scatter_kwargs = legend_mut_to_scatter[label]
                        legend_scatters.append((background_lengths * 0.5 + (
                            cur_x,
                            cur_y,
                        ), scatter_kwargs))

                legend_texts.append(
                    (label, cur_x + text_left_offset + background_lengths[0] +
                     gap_handle_to_text,
                     cur_y + text_top_offset + 0.5 + text_height / 2.0))
                cur_x += legend_item_width + tw_space * 10
                return cur_x, cur_y
Exemple #3
0
    def oncoprint(self,
                  markers,
                  annotations={},
                  title="",
                  gene_sort_method='default',
                  sample_sort_method='default',
                  figsize=[50, 20],
                  is_topplot=True,
                  is_rightplot=True,
                  is_legend=True,
                  cell_background="#dddddd",
                  gap=0.3,
                  ratio_template="{0:.0%}"):
        mutation_types = [
            b[0] for b in sorted(markers.items(),
                                 key=lambda a: a[1].get('zindex', 1))
        ]
        self.sorted_mat = self.mat
        self.sorted_genes = self.genes
        self.sorted_samples = self.samples
        self.sorted_sample_indices = list(range(len(self.samples)))
        if gene_sort_method != 'unsorted':
            if gene_sort_method == 'default':
                self._sort_genes_default()
            else:
                print("Warning: gene sorting method '%s' is not supported." %
                      gene_sort_method)
        if sample_sort_method != 'unsorted':
            if sample_sort_method == 'default':
                self._sort_samples_default(mutation_types)
            else:
                print("Warning: sample sorting method '%s' is not supported." %
                      sample_sort_method)

        if isinstance(gap, Number):
            gap = np.array([gap, gap])
        else:
            assert len(
                gap) == 2, "The length of 'gap' is only allowed to be 2."
            gap = np.array(gap)

        backgrounds = []
        background_lengths = 1.0 - gap
        t_scale = Affine2D().scale(*background_lengths)
        patch_mutations = defaultdict(lambda: [[], []])
        scatter_mutations = defaultdict(lambda: [[], []])
        stacked_counts_top = np.zeros(
            [len(mutation_types), self.sorted_mat.shape[1]])
        stacked_counts_right = np.zeros(
            [len(mutation_types), self.sorted_mat.shape[0]])
        counts_left = np.zeros(self.sorted_mat.shape[0])
        for i in range(self.sorted_mat.shape[0]):
            for j in range(self.sorted_mat.shape[1]):
                backgrounds.append(
                    Rectangle(-background_lengths / 2.0 + (
                        j,
                        i,
                    ), *background_lengths))
                if self._is_valid_string(self.sorted_mat[i, j]):
                    counts_left[i] += 1
                    for mut in np.unique(self.sorted_mat[i, j].split(
                            self.seperator)):
                        assert mut in mutation_types, "Marker for '%s' is not defined." % mut
                        stacked_counts_top[mutation_types.index(mut), j] += 1
                        stacked_counts_right[mutation_types.index(mut), i] += 1
                        ms = markers[mut]
                        if isinstance(ms['marker'],
                                      str) and (ms['marker'] == 'fill'
                                                or ms['marker'] == 'rect'):
                            patch_mutations[mut][0].append(
                                Rectangle((0, 0), 1, 1))
                            patch_mutations[mut][1].append((
                                j,
                                i,
                            ))
                        elif isinstance(ms['marker'], Patch):
                            patch_mutations[mut][0].append(copy(ms['marker']))
                            patch_mutations[mut][1].append((
                                j,
                                i,
                            ))
                        else:
                            scatter_mutations[mut][0].append(j)
                            scatter_mutations[mut][1].append(i)
        is_annot = len(annotations) > 0
        if is_annot:
            sorted_annotations = sorted(
                annotations.items(),
                key=lambda e: annotations[e[0]].get('order'))[::-1]
            ax_annot_yticks = []
            ax_annot_patches = []
            for i, (annot_type, annot_dic) in enumerate(sorted_annotations):
                annots = annot_dic['annotations'][self.sorted_sample_indices]
                annot_colors = annot_dic['colors']
                ax_annot_yticks.append(annot_type)
                for j, annot in enumerate(annots):
                    if self._is_valid_string(annot):
                        p = Rectangle(-background_lengths / 2.0 + (
                            j,
                            i,
                        ),
                                      *background_lengths,
                                      color=annot_colors[annot],
                                      lw=0)
                        ax_annot_patches.append(p)
                    elif hasattr(type(annot), '__iter__'):
                        annot_item_bottom = 0.0
                        annot_item_sum = np.sum(annot, dtype=float)
                        if annot_item_sum > 0:
                            for annot_item in annot:
                                annot_item_height = background_lengths[
                                    1] * annot_item / annot_item_sum
                                p = Rectangle(-background_lengths / 2.0 + (
                                    j,
                                    i + annot_item_bottom,
                                ),
                                              background_lengths[0],
                                              annot_item_height,
                                              color=annot_colors[annot_item],
                                              lw=0)
                                annot_item_bottom += annot_item_height
                                ax_annot_patches.append(p)
                        else:
                            p = Rectangle(-background_lengths / 2.0 + (
                                j,
                                i,
                            ),
                                          *background_lengths,
                                          color=cell_background,
                                          lw=0)
                            ax_annot_patches.append(p)
                    else:
                        p = Rectangle(-background_lengths / 2.0 + (
                            j,
                            i,
                        ),
                                      *background_lengths,
                                      color=cell_background,
                                      lw=0)
                        ax_annot_patches.append(p)
            ax_annot_pc = PatchCollection(ax_annot_patches,
                                          match_original=True)

        f = plt.figure(figsize=figsize)
        ax = host_subplot(111)
        ax_divider = make_axes_locatable(ax)

        ax_xticks = range(len(self.sorted_samples))
        ax_yticks = range(len(self.sorted_genes))
        ax.set_xticks(ax_xticks)
        ax.set_xticklabels(self.sorted_samples)
        ax.tick_params(axis='x', rotation=90)
        ax.set_yticks(ax_yticks)
        ax.set_yticklabels([
            ratio_template.format(e / float(self.mat.shape[1]))
            for e in counts_left
        ])
        ax.tick_params(top=False, bottom=False, left=False, right=False)
        for spine in ax.spines.values():
            spine.set_visible(False)
        ax.add_collection(
            PatchCollection(backgrounds, color=cell_background, linewidth=0))
        legend_mut_to_patch = {}
        legend_mut_to_scatter = {}
        for mut in mutation_types:
            ms = markers[mut]
            mk = ms['marker']
            if mut in patch_mutations:
                patches, coords = patch_mutations[mut]
                w, h = background_lengths * (
                    ms.get('width', 1.0),
                    ms.get('height', 1.0),
                )
                pc_kwargs = {
                    k: v
                    for k, v in ms.items() if not k in (
                        'marker',
                        'width',
                        'height',
                        'zindex',
                    )
                }
                if isinstance(mk, str) and (mk == 'fill' or mk == 'rect'):
                    pc_kwargs['linewidth'] = pc_kwargs.get('linewidth', 0)
                if is_legend:
                    legend_p = copy(patches[0])
                    legend_mut_to_patch[mut] = (legend_p, w, h, pc_kwargs)
                t_scale = Affine2D().scale(w, -h)
                for p, (x, y) in zip(patches, coords):
                    p.set_transform(
                        p.get_transform() + t_scale +
                        Affine2D().translate(x - w * 0.5, y + h * 0.5))
                pc = PatchCollection(patches, **pc_kwargs)
                ax.add_collection(pc)
            elif mut in scatter_mutations:
                scatter_kwargs = {
                    k: v
                    for k, v in markers[mut].items() if k != 'zindex'
                }
                if is_legend:
                    legend_mut_to_scatter[mut] = scatter_kwargs
                ax.scatter(*scatter_mutations[mut], **scatter_kwargs)

        ax2 = ax.twinx()
        ax.get_shared_y_axes().join(ax, ax2)
        ax2.set_yticks(ax_yticks)
        ax2.set_yticklabels(self.sorted_genes)
        ax2.tick_params(top=False, bottom=False, left=False, right=False)
        for spine in ax2.spines.values():
            spine.set_visible(False)

        ax_annot = None
        ax_top = None
        ax_right = None
        ax_legend = None
        #ratio_gap = gap / (len(self.sorted_genes) - gap)
        if is_annot:
            ratio_annot = (len(annotations) -
                           gap[1]) / (len(self.sorted_genes) - gap[1])
            ax_annot = ax_divider.append_axes(
                "top", size="{0:.6%}".format(ratio_annot), pad=0.2)
            ax_annot.add_collection(ax_annot_pc)
            ax_annot.set_ylim([
                len(annotations) - 1 + background_lengths[1] / 2.0,
                -background_lengths[1] / 2.0
            ])
            ax_annot.set_yticks(range(len(ax_annot_yticks)))
            ax_annot.set_yticklabels(ax_annot_yticks)
            ax.get_shared_x_axes().join(ax, ax_annot)
            ax_annot.tick_params(top=False,
                                 bottom=False,
                                 left=False,
                                 right=False,
                                 labeltop=False,
                                 labelbottom=False,
                                 labelleft=True,
                                 labelright=False)
            for spine in ax_annot.spines.values():
                spine.set_visible(False)
        if is_topplot:
            ax_top = ax_divider.append_axes("top", size=1, pad=0.2)
            ax.get_shared_x_axes().join(ax, ax_top)
            bottom = np.zeros(self.mat.shape[1])
            for idx, cnts in enumerate(stacked_counts_top):
                col = markers[mutation_types[idx]]['color']
                ax_top.bar(ax_xticks,
                           cnts,
                           color=col,
                           width=background_lengths[0],
                           bottom=bottom)
                bottom += cnts
            ax_top.yaxis.set_major_locator(MaxNLocator(integer=True))
            #ax_top.set_xlim(ax_xlim)
            ax_top.tick_params(top=False,
                               bottom=False,
                               left=True,
                               right=False,
                               labeltop=False,
                               labelbottom=False,
                               labelleft=True,
                               labelright=False)
            for idx, spine in enumerate(ax_top.spines.values()):
                if idx == 0:
                    continue
                spine.set_visible(False)
        if is_rightplot:
            ax_right = ax_divider.append_axes("right", size=2, pad=1)
            ax.get_shared_y_axes().join(ax, ax_right)
            left = np.zeros(self.mat.shape[0])
            for idx, cnts in enumerate(stacked_counts_right):
                col = markers[mutation_types[idx]]['color']
                ax_right.barh(ax_yticks,
                              cnts,
                              color=col,
                              height=background_lengths[1],
                              left=left)
                left += cnts
            ax_right.xaxis.set_major_locator(MaxNLocator(integer=True))
            ax_right.tick_params(axis='x', rotation=90)
            ax_right.tick_params(top=True,
                                 bottom=False,
                                 left=False,
                                 right=False,
                                 labeltop=True,
                                 labelbottom=False,
                                 labelleft=False,
                                 labelright=False)
            for idx, spine in enumerate(ax_right.spines.values()):
                if idx == 3:
                    continue
                spine.set_visible(False)

        ax_xlim = [
            -background_lengths[0] / 2.0,
            self.mat.shape[1] - 1 + background_lengths[0] / 2.0
        ]
        ax_ylim = [
            self.mat.shape[0] - 1 + background_lengths[1] / 2.0,
            -background_lengths[1] / 2.0
        ]
        ax.set_xlim(ax_xlim)
        ax.set_ylim(ax_ylim)

        if is_legend:
            ax_size = ax.transAxes.transform([1, 1]) / f.dpi
            ax_size_reduced = copy(ax_size)
            if is_rightplot:
                ax_size_reduced[0] -= 3  # pad + size of the plot
            ax_scale = ax_size / ax_size_reduced
            bb = _get_text_bbox(" ", ax, x=0, y=0, scale=ax_scale)
            tw_space = abs(bb.width)
            text_height = abs(bb.height)
            line_height = max(text_height, background_lengths[1])
            text_left_offset, text_top_offset = -bb.xmin, -bb.ymax
            legend_items = []
            pad_x, pad_y = -gap
            pad_x += tw_space * 5
            cur_x = pad_x
            cur_y = pad_y
            legend_patches = []
            legend_texts = []
            legend_pcs = []
            legend_scatters = []
            legend_yticks = [
                0.5,
            ]
            legend_titles = [
                'Genetic Alteration',
            ]

            gap_handle_to_text = tw_space * 2

            def add_legend_item(label, col, cur_x, cur_y, is_first, is_mut):
                legend_item_width = background_lengths[
                    0] + gap_handle_to_text + abs(
                        _get_text_bbox(label, ax, scale=ax_scale).width)
                if cur_x + legend_item_width > ax_xlim[1] and not is_first:
                    cur_x = pad_x
                    cur_y += line_height + line_height / 2.0
                p = Rectangle((cur_x, cur_y),
                              *background_lengths,
                              color=col,
                              lw=0)
                #p = Rectangle((0, 0), 1, 1, color=col)
                #p.set_transform(Affine2D().scale(*background_lengths).translate(cur_x, cur_y))
                legend_patches.append(p)
                if is_mut:
                    if label in legend_mut_to_patch:
                        p, w, h, pc_kwargs = legend_mut_to_patch[label]
                        #p.set_transform(p.get_transform() + Affine2D().scale(w, -h).translate(cur_x, cur_y + 0.5 + h * 0.5))
                        p.set_transform(
                            p.get_transform() +
                            Affine2D().scale(w, -h).translate(
                                *background_lengths * 0.5 +
                                (cur_x - 0.5 * w, cur_y + 0.5 * h)))
                        legend_pcs.append(PatchCollection([p], **pc_kwargs))
                    elif label in legend_mut_to_scatter:
                        scatter_kwargs = legend_mut_to_scatter[label]
                        legend_scatters.append((background_lengths * 0.5 + (
                            cur_x,
                            cur_y,
                        ), scatter_kwargs))

                legend_texts.append(
                    (label, cur_x + text_left_offset + background_lengths[0] +
                     gap_handle_to_text,
                     cur_y + text_top_offset + 0.5 + text_height / 2.0))
                cur_x += legend_item_width + tw_space * 10
                return cur_x, cur_y

            is_first = True
            for mut in mutation_types:
                #if is_first:
                #    debug_x = cur_x
                #    debug_y = cur_y
                cur_x, cur_y = add_legend_item(mut, cell_background, cur_x,
                                               cur_y, is_first, True)
                is_first = False

            if is_annot:
                for annot_type, annot_dic in sorted_annotations:
                    cur_x = pad_x
                    cur_y += line_height * 2.0
                    annot_colors = annot_dic['colors']
                    legend_titles.append(annot_type)
                    legend_yticks.append(cur_y + 0.5)
                    is_first = True
                    for annot_label, annot_color in sorted(
                            annot_colors.items(), key=lambda e: e[0]):
                        cur_x, cur_y = add_legend_item(annot_label,
                                                       annot_color, cur_x,
                                                       cur_y, is_first, False)
                        is_first = False

            ax_legend_height = cur_y + 1
            ax_legend_height_ratio = ax_legend_height / (
                len(self.sorted_genes) - gap[1])
            ax_legend = ax_divider.append_axes(
                "bottom",
                size="{0:.6%}".format(ax_legend_height_ratio),
                pad=1.5)
            ax_legend.set_xlim(ax_xlim)
            ax_legend.set_ylim([ax_legend_height, 0])

            #bb = _get_text_bbox("Amplification", ax)
            #p_bbox = Rectangle((debug_x + text_left_offset + background_lengths[0] + gap_handle_to_text, debug_y + text_top_offset + 0.5 + text_height / 2.0), abs(bb.width), -abs(bb.height))
            #legend_patches.append(p_bbox)

            ax_legend.set_yticks(legend_yticks)
            ax_legend.set_yticklabels(legend_titles)
            ax_legend.tick_params(top=False,
                                  bottom=False,
                                  left=False,
                                  right=False,
                                  labeltop=False,
                                  labelbottom=False,
                                  labelleft=True,
                                  labelright=False)
            for spine in ax_legend.spines.values():
                spine.set_visible(False)
            ax_legend.set_navigate(False)
            ax_legend.add_collection(
                PatchCollection(legend_patches, match_original=True))
            for pc in legend_pcs:
                ax_legend.add_collection(pc)
            for t, x, y in legend_texts:
                ax_legend.text(x, y, t)
            for (x, y), scatter_kwargs in legend_scatters:
                ax_legend.scatter([x], [y], **scatter_kwargs)

        if title != "":
            ttl = f.suptitle(title)

        return f, (ax, ax2, ax_top, ax_annot, ax_right, ax_legend)