示例#1
0
    def to_html(self, **kwargs: bool) -> str:

        if self.layout_attributes:
            for key, value in self.layout_attributes.items():
                setattr(self.content, key, value)

        # Bokeh to PDF is experimental and untested
        if kwargs.get("pdf_mode"):  # pragma: no cover
            from bokeh.io import export_svg  # type: ignore

            temp_file = Path(options._pdf_temp_dir) / f"{uuid4()}.svg"
            export_svg(self.content, filename=str(temp_file))
            html = f"<img src='{temp_file.name}' width='100%' height='auto'>\n"
            return html

        html, js = components(self.content)

        # Remove outer <div> tag so we can give our own attributes
        html = remove_outer_div(html)

        fig_width = self.content.properties_with_values().get("width", 1000)

        return ("<div class='es-bokeh-figure' "
                f"style='width: min({fig_width}px, 100%);'>"
                f"\n{html}\n{js}\n</div>")
示例#2
0
 def save(self, path, **kwargs):
     self._process_series(self._series)
     ext = os.path.splitext(path)[1]
     if ext == ".svg":
         self._fig.output_backend = "svg"
         export_svg(self.fig, filename=path)
     else:
         if ext == "":
             path += ".png"
         self._fig.output_backend = "canvas"
         export_png(self._fig, filename=path)
示例#3
0
    def to_html(self, **kwargs) -> str:

        if kwargs.get("pdf_mode"):
            from bokeh.io import export_svg  # type: ignore

            temp_file = Path(options.pdf_temp_dir) / f"{uuid4()}.svg"
            export_svg(self.content, filename=str(temp_file))
            html = f"<img src='{temp_file.name}'>\n"
            return html

        html, js = components(self.content)

        # Remove outer <div> tag so we can give our own attributes
        html = _remove_outer_div(html)

        return f"<div class='mb-3' style='width: {self.width}; height: {self.height};'>{html}\n{js}\n</div>"
示例#4
0
def heatmap(data,
            colors=None,
            title="correlation Matrix",
            size=40,
            folder='',
            interactive=False,
            pvals=None,
            maxokpval=10**-9,
            maxval=None,
            minval=None):
    """
    Make an interactive heatmap from a dataframe using bokeh

    Args:
    -----
      data: dataframe of int / float/ bool of size(names1*names2)
      colors: list[int] of size(names) a color for each names (good to display clusters)
      pvals: arraylike of int / float/ bool of size(names*val) or (names*names) with the corresponding pvalues
      maxokpval: float threshold when pvalue is considered good. otherwise lowers the size of the square
        until 10**-3 when it disappears
      title: str the plot title
      size: int the plot size
      folder: str of folder location where to save the plot, won't save if empty
      interactive: bool whether or not to make the plot interactive (else will use matplotlib)
      maxval: float clamping coloring up to maxval
      minval: float clamping coloring down to minval

    Returns:
    -------
      the bokeh object if interactive else None

    """
    regdata = data.copy()
    if minval is not None:
        data[data < minval] = minval
    if maxval is not None:
        data[data > maxval] = maxval
    data = data / data.max()
    data = data.values
    TOOLS = "hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,save"
    xname = []
    yname = []
    color = []
    alpha = []
    height = []
    width = []
    if pvals is not None:
        print(
            'we are assuming you want to display the pvals of your correlation with size'
        )
        regpvals = pvals.copy()
        u = pvals < maxokpval
        pvals[~u] = np.log10(1 / pvals[~u])
        pvals = pvals / pvals.max()
        pvals[u] = 1
    if interactive:
        xname = []
        yname = []
        color = []
        for i, name1 in enumerate(regdata.index):
            for j, name2 in enumerate(regdata.columns):
                xname.append(name2)
                yname.append(name1)
                if pvals is not None:
                    #import pdb;pdb.set_trace()
                    height.append(max(0.1, min(0.9, pvals.loc[name1][name2])))
                    color.append(cc.coolwarm[int((data[i, j] * 128) + 127)])
                    alpha.append(min(abs(data[i, j]), 0.9))
                elif other is not None:
                    color.append(cc.coolwarm[int((data[i, j] * 128) + 127)])
                    alpha.append(
                        max(min(other[i,
                                      j], 0.9), 0.1) if other[i,
                                                              j] != 0 else 0)
                else:
                    alpha.append(min(abs(data[i, j]), 0.9))
                if colors is not None:
                    if type(colors) is list:
                        if colors[i] == colors[j]:
                            color.append(Category10[10][colors[i]])
                        else:
                            color.append('lightgrey')

                elif pvals is None and other is None:
                    color.append('grey' if data[i,
                                                j] > 0 else Category20[3][2])
        if pvals is not None:
            width = height.copy()
            data = dict(xname=xname,
                        yname=yname,
                        colors=color,
                        alphas=alpha,
                        data=regdata.values.ravel(),
                        pvals=regpvals.values.ravel(),
                        width=width,
                        height=height)
        else:
            data = dict(xname=xname,
                        yname=yname,
                        colors=color,
                        alphas=alpha,
                        data=data.ravel())
        tt = [('names', '@yname, @xname'), ('value', '@data')]
        if pvals is not None:
            tt.append(('pvals', '@pvals'))
        p = figure(title=title if title is not None else "Heatmap",
                   x_axis_location="above",
                   tools=TOOLS,
                   x_range=list(reversed(
                       regdata.columns.astype(str).tolist())),
                   y_range=regdata.index.tolist(),
                   tooltips=tt)

        p.plot_width = 800
        p.plot_height = 800
        p.grid.grid_line_color = None
        p.axis.axis_line_color = None
        p.axis.major_tick_line_color = None
        p.axis.major_label_text_font_size = "5pt"
        p.axis.major_label_standoff = 0
        p.xaxis.major_label_orientation = np.pi / 3
        p.output_backend = "svg"
        p.rect('xname',
               'yname',
               width=0.9 if not width else 'width',
               height=0.9 if not height else 'height',
               source=data,
               color='colors',
               alpha='alphas',
               line_color=None,
               hover_line_color='black',
               hover_color='colors')
        save(p, folder + title.replace(' ', "_") + "_heatmap.html")
        export_svg(p,
                   filename=folder + title.replace(' ', "_") +
                   "_correlation.svg")
        try:
            show(p)
        except:
            show(p)
        return p  # show the plot
    else:
        plt.figure(figsize=size)
        plt.title('the correlation matrix')
        plt.imshow(data)
        plt.savefig(title + "_correlation.pdf")
        plt.show()
示例#5
0
def scatter(data,
            labels=None,
            title='scatter plot',
            showlabels=False,
            folder='',
            colors=None,
            xname='',
            yname="",
            importance=None,
            radi=5,
            alpha=0.8,
            **kwargs):
    """
    Makes an interactive scatter plot using Bokeh

    Args:
    -----
      data: array-like with shape [N,2]
      labels: list[str] a list of N names for each points
      title: str the plot title
      showlabels: bool if the labels should be always displayed or not (else just on hover)
      colors: list[int] of N integers from 0 up to 256 for the dot's colors
      folder: str of location where to save the plot, won't save if empty
      xname: str the name of the x axes
      yname: str the name of the y axes
      importance: a list[int] of N values to scale the size of the dots and their opacity by
      radi: int the size of the dots
      alpha: float the opacity of the dots
      **kwargs: additional bokeh.figure args

    Returns:
    ------
      the bokeh object
    """
    TOOLS = "hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,save,box_select,lasso_select,"

    col = viridis(len(set(colors))) if colors is not None else ['#29788E'
                                                                ]  # (viridis1)
    radii = []
    fill_alpha = []
    cols = []
    for i in range(data.shape[0]):
        radii.append(radi if importance is None else radi / 2 +
                     importance[i] * 30)
        fill_alpha.append(alpha if importance is None else alpha -
                          (0.2 * importance[i]))
        cols.append(col[0] if colors is None else col[int(colors[i])])
    source = ColumnDataSource(
        data=dict(x=data[:, 0],
                  y=data[:, 1],
                  labels=labels if labels is not None else [''] * len(radii),
                  fill_color=cols,
                  fill_alpha=fill_alpha,
                  radius=radii))
    TOOLTIPS = [
        ("name", "@labels"),
        ("(x,y)", "(@x, @y)"),
    ]
    p = figure(tools=TOOLS, tooltips=TOOLTIPS, title=title)
    p.circle('x',
             'y',
             color='fill_color',
             fill_alpha='fill_alpha',
             line_width=0,
             radius='radius' if radi else None,
             source=source)
    p.xaxis[0].axis_label = xname
    p.yaxis[0].axis_label = yname
    if showlabels:
        labels = LabelSet(x='x',
                          y='y',
                          text='labels',
                          level='glyph',
                          text_font_size='9pt',
                          x_offset=5,
                          y_offset=5,
                          source=source,
                          render_mode='canvas')
        p.add_layout(labels)
    p.output_backend = "svg"
    try:
        show(p)
    except:
        show(p)
    if folder:
        save(p, folder + title.replace(' ', "_") + "_scatter.html")
        export_svg(p,
                   filename=folder + title.replace(' ', "_") + "_scatter.svg")
    return p
示例#6
0
def volcano(data,
            folder='',
            tohighlight=None,
            tooltips=[('gene', '@gene_id')],
            title="volcano plot",
            xlabel='log-fold change',
            ylabel='-log(Q)',
            maxvalue=100,
            searchbox=False,
            logfoldtohighlight=0.15,
            pvaltohighlight=0.1,
            showlabels=False):
    """
    Make an interactive volcano plot from Differential Expression analysis tools outputs

    Args:
    -----
      data: a df with rows genes and cols [log2FoldChange, pvalue, gene_id]
      folder: str of location where to save the plot, won't save if empty
      tohighlight: list[str] of genes to highlight in the plot
      tooltips: list[tuples(str,str)] if user wants tot specify another bokeh tooltip
      title: str plot title
      xlabel: str if user wants to specify the title of the x axis
      ylabel: str if user wants tot specify the title of the y axis
      maxvalue: float the max -log2(pvalue authorized usefull when managing inf vals)
      searchbox: bool whether or not to add a searchBox to interactively highlight genes
      logfoldtohighlight: float min logfoldchange when to diplay points
      pvaltohighlight: float min pvalue when to diplay points
      showlabels: bool whether or not to show a text above each datapoint with its label information

    Returns:
    --------
      The bokeh object
    """
    # pdb.set_trace()
    to_plot_not, to_plot_yes = selector(
        data, tohighlight if tohighlight is not None else [],
        logfoldtohighlight, pvaltohighlight)
    hover = bokeh.models.HoverTool(tooltips=tooltips, names=['circles'])

    # Create figure
    p = bokeh.plotting.figure(title=title, plot_width=650, plot_height=450)

    p.xgrid.grid_line_color = 'white'
    p.ygrid.grid_line_color = 'white'
    p.xaxis.axis_label = xlabel
    p.yaxis.axis_label = ylabel

    # Add the hover tool
    p.add_tools(hover)
    p, source1 = add_points(p,
                            to_plot_not,
                            'log2FoldChange',
                            'pvalue',
                            color='#1a9641',
                            maxvalue=maxvalue)
    p, source2 = add_points(p,
                            to_plot_yes,
                            'log2FoldChange',
                            'pvalue',
                            color='#fc8d59',
                            alpha=0.6,
                            outline=True,
                            maxvalue=maxvalue)
    if showlabels:
        labels = LabelSet(x='log2FoldChange',
                          y='transformed_q',
                          text_font_size='7pt',
                          text="gene_id",
                          level="glyph",
                          x_offset=5,
                          y_offset=5,
                          source=source2,
                          render_mode='canvas')
        p.add_layout(labels)
    if searchbox:
        text = TextInput(title="text", value="gene")
        text.js_on_change(
            'value',
            CustomJS(args=dict(source=source1),
                     code="""
      var data = source.data
      var value = cb_obj.value
      var gene_id = data.gene_id
      var a = -1
      for (i=0; i < gene_id.length; i++) {
          if ( gene_id[i]===value ) { a=i; console.log(i); data.size[i]=7; data.alpha[i]=1; data.color[i]='#fc8d59' }
      }
      source.data = data
      console.log(source)
      console.log(cb_obj)
      source.change.emit()
      console.log(source)
      """))
        p = column(text, p)
    p.output_backend = "svg"
    if folder:
        save(p, folder + title.replace(' ', "_") + "_volcano.html")
        export_svg(p,
                   filename=folder + title.replace(' ', "_") + "_volcano.svg")
    try:
        show(p)
    except:
        show(p)
    return p
示例#7
0
def CNV_Map(df,
            sample_order=[],
            title="CN heatmaps sorted by SMAD4 loss, pointing VPS4B",
            width=900,
            height=400,
            standoff=10,
            y_label='',
            marks=[]):
    """
    create an interactive plot suited for visualizing segment level CN data for a set of samples using bokeh

    args:
    ----
      df: df['Sample' 'Start' 'End' 'Segment_Mean' 'size'] the df containing segment level
        copy number (can be subsetted to a specific region or genome-wide)
      sampleorder: list[Sample] <- for all samples present in the df
      title: plot title
      width: int width
      height: int height
      standoff: the space between the plot and the x axis
      y_label: the y axis label
      marks: location of lines at specific loci

    Returns:
    --------
      The bokeh object
    """
    colors = [
        "#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1",
        "#cc7878", "#933b41", "#550b1d"
    ]
    colors = RdBu[8]
    mapper = LinearColorMapper(palette=colors,
                               low=df.Segment_Mean.min(),
                               high=df.Segment_Mean.max())
    if len(sample_order) == 0:
        sample_order = list(set(df.Sample.tolist()))
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    p = figure(title=title,
               y_range=(df.End.max(), df.Start.min()),
               x_range=sample_order,
               x_axis_location="above",
               plot_width=width,
               plot_height=height,
               tools=TOOLS,
               toolbar_location='below',
               tooltips=[('pos', '@Start, @End'), ('relative CN', '@Sample')])

    p.grid.grid_line_color = None
    p.axis.axis_line_color = None
    p.axis.major_tick_line_color = None
    p.axis.major_label_text_font_size = "5pt"
    p.axis.major_label_standoff = standoff
    p.xaxis.major_label_orientation = pi / 3
    pos = 0
    # for i,val in enumerate(historder):
    #    p.rect(x=pos,y=-7,width=len(orderbyhist[val]), height=10, fill_color=small_palettes['Viridis'][4][i])
    #    p.text(x=pos+len(orderbyhist[val])/2, y=-9, text=str(val), text_color="#96deb3")
    #    pos += len(orderbyhist[val])

    p.rect(x="Sample",
           y="Start",
           width=0.9,
           height="size",
           source=df.reset_index(drop=True),
           fill_color={
               'field': 'Segment_Mean',
               'transform': mapper
           },
           line_color=None)

    color_bar = ColorBar(color_mapper=mapper,
                         major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         formatter=PrintfTickFormatter(format="%.2f"),
                         label_standoff=6,
                         border_line_color=None,
                         location=(0, 0))
    p.add_layout(color_bar, 'right')
    p.yaxis.axis_label = y_label
    # p.yaxis.major_label_overrides={20:'Centromer'}
    for val in marks:
        hline = Span(location=val,
                     dimension='width',
                     line_color='green',
                     line_width=0.2)
        p.renderers.extend([hline])
    p.output_backend = "svg"
    if folder:
        save(p, folder + title.replace(' ', "_") + "_cn_plot.html")
        export_svg(p,
                   filename=folder + title.replace(' ', "_") + "_cn_plot.svg")
    show(p)  # show the plot
    return p
示例#8
0
def bigScatter(data,
               precomputed=False,
               logscale=False,
               features=False,
               title="BigScatter",
               binsize=0.1,
               folder="",
               showpoint=False):
    """
    uses a binning method to display millions of points at the same time and showcase density.

    Does this in an interactive fashion

    Args:
    -----
      data: array like. the array containing the point location x,y or their location and density of bins (q,r,c)
      precomputed: bool whether or not the array has aleady been hexbined
      logscale: bool, whether or not the data is logscaled
      features: list[] if the matrix contains a feature column with feature information (names, values. for each bin/dot)
      title: str the title of the plot
      binsize: float the size of the bins
      showpoint: bool whether or not to display them as points or hexes.
      folder: str of location where to save the plot, won't save if empty

    Returns:
    ------
      the bokeh object
    """
    TOOLS = "wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,save,box_select,lasso_select,"
    names = [("count", "@c")]
    if features:
        names.append(('features', '@features'))
    if precomputed:
        TOOLS = "hover," + TOOLS
    p = figure(title=title,
               tools=TOOLS,
               tooltips=names if precomputed else None,
               match_aspect=True,
               background_fill_color='#440154')
    if precomputed:
        p.hex_tile(q="q",
                   r="r",
                   size=binsize,
                   line_color=None,
                   source=data,
                   hover_color="pink",
                   hover_alpha=0.8,
                   fill_color=linear_cmap('c', 'Viridis256', 0, max(data.c))
                   if not logscale else {
                       'field': 'c',
                       'transform': LogColorMapper('Viridis256')
                   })
    else:
        if features:
            print("we cannot yet process features on non precomputed version")
        r, bins = p.hexbin(data[:, 0],
                           data[:, 1],
                           line_color=None,
                           size=binsize,
                           hover_color="pink",
                           hover_alpha=0.8,
                           fill_color=linear_cmap('c', 'Viridis256', 0, None)
                           if not logscale else {
                               'field': 'c',
                               'transform': LogColorMapper('Viridis256')
                           })
    p.grid.visible = False
    if showpoint:
        p.circle(data[:, 0], data[:, 1], color="white", size=1)

    if not precomputed:
        p.add_tools(
            HoverTool(tooltips=names,
                      mode="mouse",
                      point_policy="follow_mouse",
                      renderers=[r] if not precomputed else None))
    p.output_backend = "svg"
    try:
        show(p)
    except:
        show(p)
    if folder:
        save(p, folder + title.replace(' ', "_") + "_scatter.html")
        export_svg(p,
                   filename=folder + title.replace(' ', "_") + "_scatter.svg")
    return p
示例#9
0
def scatter(data,
            labels=None,
            title='scatter plot',
            showlabels=False,
            folder='',
            colors=None,
            xname='',
            yname="",
            importance=None,
            radi=5,
            alpha=0.8,
            colprovided=False,
            shape=None,
            **kwargs):
    """
    Makes an interactive scatter plot using Bokeh

    Args:
    -----
        data: array-like with shape [N,2]
        labels: list[str] a list of N names for each points or dict[str, list[str]] if you want multiple labels
        title: str the plot title
        showlabels: bool if the labels should be always displayed or not (else just on hover)
        colors: list[int] of N integers from 0 up to 256 for the dot's colors
        folder: str of location where to save the plot, won't save if empty
        xname: str the name of the x axes
        yname: str the name of the y axes
        importance: a list[int] of N values to scale the size of the dots and their opacity by
        radi: int the size of the dots
        alpha: float the opacity of the dots
        **kwargs: additional bokeh.figure args

    Returns:
    ------
        the bokeh object
    """
    TOOLS = "hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,save,box_select,lasso_select,"

    radii = []
    fill_alpha = []
    cols = []

    col = viridis(len(set(colors))) if colors is not None else ['#29788E'
                                                                ]  # (viridis1)
    for i in range(data.shape[0]):
        radii.append(radi if importance is None else radi /
                     (1 + importance[i]))
        fill_alpha.append(alpha if importance is None else alpha -
                          (0.2 * importance[i]))
        if not colprovided:
            cols.append(col[0] if colors is None else col[int(colors[i])])

    if shape is None:
        shape = [0] * data.shape[0]
    shape = np.array(shape)
    TOOLTIPS = [
        ("(x,y)", "(@x, @y)"),
    ]
    if type(labels) is list:
        TOOLTIPS.append(("label", "@labels"))
    elif type(labels) is dict:
        TOOLTIPS.extend([(str(i), "@" + str(i)) for i in list(labels.keys())])

    p = figure(tools=TOOLS, tooltips=TOOLTIPS, title=title)

    shaplot = {
        0: p.circle,
        1: p.star,
        2: p.square,
        3: p.triangle,
        4: p.cross,
        5: p.hex,
        6: p.diamond,
        7: p.inverted_triangle
    }

    shape_encoder = {val: i for i, val in enumerate(set(shape))}
    if len(set(shape)) > 8:
        raise ValueError("Too many shapes")
    for val in set(shape):
        di = dict(
            x=data[shape == val, 0],
            y=data[shape == val, 1],
            fill_color=np.array(cols)[shape == val]
            if not colprovided else np.array(colors)[shape == val],
            fill_alpha=np.array(fill_alpha)[shape == val],
            radius=np.array(radii)[shape == val],
        )

        if type(labels) is list:
            di.update({'labels': np.array(labels)[shape == val]})
        elif type(labels) is dict:
            di.update({
                va: np.array(label)[shape == val]
                for va, label in labels.items()
            })

        source = ColumnDataSource(data=di)

        shaplot[shape_encoder[val]]('x',
                                    'y',
                                    color='fill_color',
                                    fill_alpha='fill_alpha',
                                    line_width=0,
                                    source=source)
    p.xaxis[0].axis_label = xname
    p.yaxis[0].axis_label = yname
    if showlabels:
        labels = LabelSet(x='x',
                          y='y',
                          text='labels',
                          level='glyph',
                          text_font_size='9pt',
                          x_offset=5,
                          y_offset=5,
                          source=source,
                          render_mode='canvas')
        p.add_layout(labels)
    p.output_backend = "svg"
    try:
        show(p)
    except:
        show(p)
    if folder:
        save(p, folder + title.replace(' ', "_") + "_scatter.html")
        export_svg(p,
                   filename=folder + title.replace(' ', "_") + "_scatter.svg")
    return p