Example #1
0
        def make_document(doc: Document):
            doc.title = "Backtrader Optimization Result"

            env = Environment(
                loader=PackageLoader('backtrader_plotting.bokeh', 'templates'))
            doc.template = env.get_template("basic.html.j2")

            model = self.generate_optresult_model(result, columns)
            doc.add_root(model)
Example #2
0
    def go(self):

        """Displays the application"""

        document = Document()
        document.title = "UT330 UI"
        document.add_root(self.tabs)
        session = push_session(document)
        session.show()

        session.loop_until_closed()
Example #3
0
        def make_document(doc: Document):
            doc.title = "Backtrader Optimization Result"

            env = Environment(
                loader=PackageLoader('backtrader_plotting.bokeh', 'templates'))
            doc.template = env.get_template("basic.html.j2")

            doc.template_variables['stylesheet'] = utils.generate_stylesheet(
                self._bokeh.params.scheme)

            model = self._build_optresult_model()
            doc.add_root(model)
Example #4
0
def get_bokeh_script(user, plot, suffix):
    from .models import UserSession

    document = Document()
    document.add_root(plot)
    document.title = suffix

    with closing(push_session(document)) as session:
        # Save the session id to a UserSession
        UserSession.objects.create(user=user, bokeh_session_id=session.id)
        # Get the script to pass into the template
        script = autoload_server(None, session_id=session.id)

    return script
Example #5
0
        def make_document(doc: Document):
            if self._on_session_destroyed is not None:
                doc.on_session_destroyed(self._on_session_destroyed)

            # set document title
            doc.title = self._title

            # set document template
            env = Environment(loader=PackageLoader('backtrader_plotting.bokeh', 'templates'))
            doc.template = env.get_template(self._html_template)
            doc.template_variables['stylesheet'] = utils.generate_stylesheet(self._scheme)

            # get root model
            model = self._model_factory_fnc(doc)
            doc.add_root(model)
Example #6
0
        def make_document(doc: Document):
            if self._on_session_destroyed is not None:
                doc.on_session_destroyed(self._on_session_destroyed)

            # set document title
            doc.title = self._title

            # set document template
            now = datetime.now()
            env = Environment(loader=PackageLoader('btplotting', 'templates'))
            templ = env.get_template(self._html_template)
            templ.globals['now'] = now.strftime('%Y-%m-%d %H:%M:%S')
            doc.template = templ
            doc.template_variables['stylesheet'] = generate_stylesheet(
                self._scheme)
            model = self._model_factory_fnc(doc)
            doc.add_root(model)
Example #7
0
 def plot_code_iterator(self):
     """
     Iterator over the single bokeh plot
     :return: Tuple of js-script code for the plot and number of invalid
     values
     """
     for index, dummy in enumerate(self.__conf.filter_args):
         if self.__index is not None and self.__index != index:
             continue
         document = Document()
         document.title = self.__conf.description
         self.__factors, self.__values, num_invalid = \
             self.create_x_y_values(index)
         plot = self.__create_control_chart_hist(index)
         document.add_root(plot)
         session_id = self.__save_user_session(document, index)
         script = autoload_server(None, session_id=session_id)
         yield script, num_invalid
Example #8
0
def density_handler(doc: Document) -> None:
    """
    Handler function for the density application.
    """

    task_id = doc.session_context.request.arguments.get('task_id')
    username = doc.session_context.request.arguments.get('username')
    user_dir = os.path.join(settings.USER_DATA, username)
    path_to_db = os.path.join(user_dir, task_id)

    try:
        conn = os.path.join(path_to_db, task_id + '.csv')
        df = pd.read_csv(conn)

        proteins = list(df.Protein.unique())
        lipids = list(df.Lipids.unique())
    except:
        proteins, lipids = [], []

        for o in os.listdir(path_to_db):
            key = o.split('/')[-1]
            if key.endswith('.npy'):
                if key.startswith('prot_'):
                    proteins.append('Protein(s)')
                else:
                    lipid = key.split('_')[0]
                    lipids.append(lipid)

    all_mpl_cmaps = [
        'viridis',
        'plasma',
        'inferno',
        'cividis',
        'Greys',
        'Purples',
        'Blues',
        'Greens',
        'Oranges',
        'Reds',
        'RdYlBu',
        'RdYlGn',
        'Spectral',
        'Spectral_r',
        'coolwarm',
        'coolwarm_r',
        'seismic',
        'YlOrBr',
        'YlOrRd',
        'OrRd',
        'PuRd',
        'RdPu',
        'BuPu',
        'GnBu',
        'PuBu',
        'YlGnBu',
        'PuBuGn',
        'BuGn',
        'YlGn',
        'PiYG',
        'PRGn',
        'BrBG',
        'PuOr',
        'RdGy',
        'RdBu',
    ]

    #TODO: globals declaration should not be necessary anymore.
    global prot_xyz
    prot_xyz = np.load(os.path.join(path_to_db, "prot_" + task_id + '.npy'))

    global l_xyz
    global x_min, x_max, y_min, y_max, z_min, z_max

    l_xyz = np.load(
        os.path.join(path_to_db, lipids[0] + "_" + task_id + '.npy'))

    x_min, x_max = l_xyz[:, 0].min(), l_xyz[:, 0].max()
    y_min, y_max = l_xyz[:, 1].min(), l_xyz[:, 1].max()
    z_min, z_max = l_xyz[:, 2].min(), l_xyz[:, 2].max()

    # widgets
    color_map = Select(title="Colormap",
                       value="viridis",
                       options=all_mpl_cmaps,
                       width=120)

    lipid = Select(title="Lipids", value=lipids[0], options=lipids, width=100)

    denstype = Select(title="Density Type",
                      value="All Proteins",
                      options=["All Proteins", "Average"],
                      width=120)

    number = Slider(title="Number of Bins",
                    value=380,
                    start=80,
                    end=500,
                    step=10,
                    width=200)

    protein = Select(title="Show Protein",
                     value="No",
                     options=["Yes", "No"],
                     width=90)

    gpcr = Select(title="Protein",
                  value=proteins[0],
                  options=proteins,
                  width=130)

    zrange = RangeSlider(start=z_min,
                         end=z_max,
                         value=(z_min, z_max),
                         step=0.2,
                         title="Z-Axis Range",
                         callback_policy='mouseup',
                         width=352)

    cbar_range = Slider(value=256,
                        start=0,
                        end=256,
                        step=1,
                        height=600,
                        orientation='vertical',
                        callback_policy='mouseup',
                        margin=(15, 0),
                        tooltips=False,
                        show_value=False)

    # colorschemes
    colormap = cm.get_cmap(color_map.value)
    bokehpalette = [
        mpl.colors.rgb2hex(m) for m in colormap(np.arange(colormap.N))
    ]

    def lipid_density(array, bins=160):
        """Given a 2D array, containing the x, y values of a lipid,
        return its histogram with edges."""
        x = array[:, 0]
        y = array[:, 1]

        lipid, e1, e2 = np.histogram2d(x, y, density=True, bins=bins)

        return lipid, e1, e2

    # Plot histogram image
    H, xe, ye = lipid_density(l_xyz, number.value)
    minx = np.abs(xe.min())
    miny = np.abs(ye.min())

    p1 = figure(plot_height=640, plot_width=640, tools='')
    image_source = ColumnDataSource(data=dict(image=[]))
    img = p1.image(image="image",
                   x=xe[0],
                   y=ye[0],
                   dw=xe[-1] + minx,
                   dh=ye[-1] + miny,
                   palette=bokehpalette,
                   source=image_source)

    circle_prot_source = ColumnDataSource(
        data=dict(x1=prot_xyz[:, 0], y1=prot_xyz[:, 1]))
    p1.circle(x="x1",
              y="y1",
              source=circle_prot_source,
              size=2,
              fill_alpha=0.2)

    cb_palette = LinearColorMapper(palette=bokehpalette,
                                   low=H.min(),
                                   high=H.max())
    color_bar = ColorBar(color_mapper=cb_palette,
                         width=8,
                         location=(0, 0),
                         label_standoff=10)
    color_bar.formatter = BasicTickFormatter(use_scientific=False)
    p1.add_layout(color_bar, 'right')

    # Make graph pretty
    p1.xgrid.grid_line_color = None
    p1.ygrid.grid_line_color = None
    p1.xaxis.major_tick_line_color = None
    p1.xaxis.minor_tick_line_color = None
    p1.yaxis.major_tick_line_color = None
    p1.yaxis.minor_tick_line_color = None
    p1.xaxis.major_label_text_font_size = '0pt'
    p1.yaxis.major_label_text_font_size = '0pt'
    p1.grid.visible = False
    p1.toolbar.logo = None
    p1.toolbar_location = None

    def update_all(cond=False, cmap=False):
        """
        Update the image showing all proteins.
        """
        if cond:
            # For efficiency execute only if GPCR structure changes
            global l_xyz
            global x_min, x_max, y_min, y_max, z_min, z_max

            l_xyz = np.load(
                os.path.join(path_to_db,
                             str(lipid.value) + "_" + task_id + '.npy'))
            x_min, x_max = l_xyz[:, 0].min(), l_xyz[:, 0].max()
            y_min, y_max = l_xyz[:, 1].min(), l_xyz[:, 1].max()
            z_min, z_max = l_xyz[:, 2].min(), l_xyz[:, 2].max()
            zrange.start = z_min
            zrange.end = z_max

            index = np.where((l_xyz[:, 2] > zrange.value[0])
                             & (l_xyz[:, 2] < zrange.value[1]))
            l_xyz_new = l_xyz[index]
        else:
            l_xyz_new = l_xyz

        if cmap:
            # For efficiency execute only if image colormap changes
            cb_cut_value = 256 - cbar_range.value

            cmap = color_map.value
            colormap = cm.get_cmap(cmap)
            bokehpalette = [
                mpl.colors.rgb2hex(m) for m in colormap(np.arange(colormap.N))
            ]
            bp_i = 0
            while bp_i < len(bokehpalette[:cb_cut_value]):
                bokehpalette[bp_i] = '#ffffff'
                bp_i += 1

            img.glyph.color_mapper.palette = bokehpalette
            color_bar.color_mapper.palette = bokehpalette

        # Update histogram image
        H, xe, ye = lipid_density(l_xyz_new, number.value)
        minx = np.abs(xe.min())
        miny = np.abs(ye.min())

        img.glyph.dw = xe[-1] + minx
        img.glyph.dh = ye[-1] + miny

        # update image source
        image_source.data = dict(image=[H])

    def update_protein(cond=False):
        """
        Update the protein representation.
        """
        if cond:
            # For efficiency execute only if GPCR structure changes
            global prot_xyz

        if protein.value == "Yes":
            circle_prot_source.data = dict(x1=prot_xyz[:, 0],
                                           y1=prot_xyz[:, 1])

        elif protein.value == "No":
            circle_prot_source.data = dict(x1=[], y1=[])

    def update_cbar():

        cb_cut_value = 256 - cbar_range.value

        cmap = color_map.value
        colormap = cm.get_cmap(cmap)
        bokehpalette = [
            mpl.colors.rgb2hex(m) for m in colormap(np.arange(colormap.N))
        ]

        bp_i = 0
        while bp_i < len(bokehpalette[:cb_cut_value]):
            bokehpalette[bp_i] = '#ffffff'
            bp_i += 1

        img.glyph.color_mapper.palette = bokehpalette
        color_bar.color_mapper.palette = bokehpalette

    # event listeners
    controls = [lipid, zrange, gpcr]
    for control in controls:
        control.on_change('value',
                          lambda attr, old, new: update_denstype(cond=True))

    number.on_change('value', lambda attr, old, new: update_denstype())
    color_map.on_change('value',
                        lambda attr, old, new: update_denstype(cmap=True))
    protein.on_change('value', lambda attr, old, new: update_protein())
    denstype.on_change('value', lambda attr, old, new: update_denstype())
    cbar_range.on_change('value', lambda attr, old, new: update_cbar())

    # deal with what gets updated and what not.
    def update_denstype(cond=False, cmap=False):
        update_all(cond, cmap)
        update_protein(cond)

    update_denstype()
    input1 = row([gpcr, lipid, color_map, protein])
    input2 = row([p1, cbar_range])
    input3 = row([number, zrange])
    input3 = column([input1, input2, input3])

    l = layout([input3])

    doc.add_root(l)
    doc.title = "Density App"
Example #9
0
def scatter_handler(doc: Document) -> None:
    """
    Handler function for the scatter application.
    """

    # Load data
    task_id = doc.session_context.request.arguments.get('task_id')
    username = doc.session_context.request.arguments.get('username')
    user_dir = os.path.join(settings.USER_DATA, username)
    path_to_db = os.path.join(user_dir, task_id)
    conn = os.path.join(path_to_db, task_id + '.csv')
    df = pd.read_csv(conn)

    for col in df.columns:
        if col.endswith('Error'):
            if df[col].max() == 0:
                del df[col]

    # widgets
    radii = [str(x) for x in df.Radius.unique()]
    number = Slider(title="Value Cutoff", value=0, start=0, end=4, step=0.1, width=150)
    residue = TextInput(title="Residue name (3 letter code):", width=200)
    gpcr = Select(title="Proteins", value=list(df.Protein.unique())[0],
                options=list(df.Protein.unique()), width=100)
    lipid = Select(title="Lipids", value=list(df.Lipids.unique())[0],
                options=list(df.Lipids.unique()), width=100)
    radius = Select(title="Radius", value=radii[-1], options=radii, width=100)
    options = list(df.columns)[:-5] + ['ResID']
    x_axis = Select(title="X Axis", options=options, value="ResID", width=150)
    y_axis = Select(title="Y Axis", options=options, value=options[0], width=150)

    # colors and plotting
    cc_colors = [x for x in cc.all_original_names() if x.startswith('linear') or x.startswith('rainbow')]
    cmap = Select(title="Colormap", options=cc_colors, value='linear_kryw_0_100_c71', width=150)
    # Create Column Data Source that will be used by the plot
    source = ColumnDataSource(data=dict(x=[], y=[], ResName=[], ResID=[], Protein=[]))
    TOOLTIPS=[
        ("ResName", "@ResName"),
        ("ResID", "@ResID"),
        ("Value", "@y")
    ]
    point_color_mapper = linear_cmap(field_name='y', palette=cc.CET_L19,
                        low=df[df.Protein == gpcr.value][y_axis.value].min(),
                        high=df[df.Protein == gpcr.value][y_axis.value].max())
    p = figure(plot_height=400, plot_width=800, tooltips=TOOLTIPS,)

    circle_plot = p.circle(x="x", y="y", source=source, line_color='black', fill_color=point_color_mapper, size=7)
    circle_object = {'circle': circle_plot}

    # make plot pretty
    p.toolbar.autohide = True
    p.axis.axis_label_text_font_size = "12pt"
    p.axis.axis_label_text_font_style = "bold"
    p.title.align = 'center'

    def update(df):
        y_value = y_axis.value
        x_value = x_axis.value

        df = df[
            (df[y_value] >= number.value) &
            (df['Protein'] == gpcr.value) &
            (df['Lipids'] == lipid.value) &
            (df['Radius'] == float(radius.value))
        ]
        if (residue.value != ""):
            df = df[df.ResName.str.contains(residue.value.upper())==True]

        point_color_mapper = linear_cmap(field_name='y', palette=cc.palette[cmap.value],
                            low=df[df.Protein == gpcr.value][y_value].min(),
                            high=df[df.Protein == gpcr.value][y_value].max())

        circle_object['circle'].glyph.fill_color = point_color_mapper

        p.xaxis.axis_label = x_value
        p.yaxis.axis_label = y_value
        p.title.text = "Showing %d Data Points  " % len(df)

        source.data = dict(
            x=df[x_value],
            y=df[y_value],
            ResName=df["ResName"],
            ResID=df["ResID"],
            Protein=df["Protein"],
        )

    # add controls
    controls = [number, gpcr, lipid, radius, y_axis, x_axis, residue, cmap]
    for control in controls:
        control.on_change('value', lambda attr, old, new: update(df))

    # build layout
    # TODO: this should be made easier to read
    sizing_mode = 'scale_width'
    inputs2 = row([gpcr, lipid, radius, residue], sizing_mode=sizing_mode)
    inputs3 = row([number, x_axis, y_axis, cmap], sizing_mode=sizing_mode)
    layout1 = layout([[inputs2]], sizing_mode=sizing_mode)
    layout2 = layout([p], sizing_mode=sizing_mode)
    layout3 = layout([inputs3], sizing_mode="scale_width")

    # render
    update(df)
    doc.add_root(layout1)
    doc.add_root(layout2)
    doc.add_root(layout3)
    doc.title = "Point Application"
Example #10
0
def radar_handler(doc: Document) -> None:
    """
    Handler function for the radar application.
    """

    # Load data.
    task_id = doc.session_context.request.arguments.get('task_id')
    username = doc.session_context.request.arguments.get('username')
    user_dir = os.path.join(settings.USER_DATA, username)
    path_to_db = os.path.join(user_dir, task_id)
    conn = os.path.join(path_to_db, task_id + '.csv')
    df = pd.read_csv(conn)

    for col in df.columns:
        if col.endswith('Error'):
            del df[col]

    # NOTE: How does this fare with multiple different proteins? And should we care?
    gpcrs = list(df.Protein.unique())
    lipids = list(df.Lipids.unique())
    radius = list(df.Radius.unique())
    radius = [str(r) for r in radius]

    # NOTE: every metric is normalized with respect to itself!
    # Normalize [0-1] all contact parameters with respect to each other.
    # TODO: There are better ways of doing this! This app needs to be improved.
    for cmn in list(df.columns)[:6]:
        for lipid in lipids:
            for radius_value in radius:
                radius_value = float(radius_value)

                dfmin = df[(df.Lipids == lipid)
                           & (df.Radius == radius_value)][cmn].min()

                dfmax = df[(df.Lipids == lipid)
                           & (df.Radius == radius_value)][cmn].max()

                lip_index = list(df[(df.Lipids == lipid)
                                    & (df.Radius == radius_value)].index)

                df.loc[lip_index,
                       cmn] = df[(df.Lipids == lipid)
                                 & (df.Radius == radius_value)][cmn].apply(
                                     lambda x: (x - dfmin) / (dfmax - dfmin))

    df = df.fillna(0)

    # TODO: It is better to simply remove residues with zero contacts so they do not overcrowd the selection box.
    # 1 unique set of residues - works also if there's only 1 set available.
    resname = df[(df.Protein == gpcrs[0]) & (df.Lipids == lipids[0]) &
                 (df.Radius == float(radius[0]))].ResName.to_list()
    resid = df[(df.Protein == gpcrs[0]) & (df.Lipids == lipids[0]) &
               (df.Radius == float(radius[0]))].ResID.to_list()

    residues = []
    for rn, ri in zip(resname, resid):
        residues.append("{}-{}".format(rn, ri))

    # random starting values
    import random
    # Create Input controls
    gpcr1 = Select(title="Protein", value=gpcrs[0], options=gpcrs, width=100)
    gpcr2 = Select(title="Protein", value=gpcrs[0], options=gpcrs, width=100)
    lipid1 = Select(title="Lipids", value=lipids[0], options=lipids, width=100)
    lipid2 = Select(title="Lipids", value=lipids[0], options=lipids, width=100)
    residue1 = Select(title="Residue",
                      value=random.choice(residues),
                      options=residues,
                      width=120)
    residue2 = Select(title="Residue",
                      value=random.choice(residues),
                      options=residues,
                      width=120)
    radius1 = Select(title="Radius",
                     value=radius[0],
                     options=radius,
                     width=100)
    radius2 = Select(title="Radius",
                     value=radius[0],
                     options=radius,
                     width=100)

    def unit_poly_verts(theta, centre):
        """Return vertices of polygon for subplot axes.
        This polygon is circumscribed by a unit circle centered at (0.5, 0.5)
        """
        x0, y0, r = [centre] * 3
        verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta]
        return verts

    def radar_patch(r, theta, centre):
        """ Returns the x and y coordinates corresponding to the magnitudes of
        each variable displayed in the radar plot
        """
        # offset from centre of circle
        offset = 0
        yt = (r * centre + offset) * np.sin(theta) + centre
        xt = (r * centre + offset) * np.cos(theta) + centre
        return list(xt), list(yt)

    # We need to make the plot pretty!
    def star_curv(old_x, old_y):
        """ Interpolates every point by a star-shaped curv. It does so by adding
        "fake" data points in-between every two data points, and pushes these "fake"
        points towards the center of the graph (roughly 1/4 of the way).
        """

        try:
            points = np.array([old_x, old_y]).reshape(7, 2)
            hull = ConvexHull(points)
            x_mid = np.mean(hull.points[hull.vertices, 0])
            y_mid = np.mean(hull.points[hull.vertices, 1])
        except:
            x_mid = 0.5
            y_mid = 0.5

        c = 1
        x, y = [], []
        for i, j in zip(old_x, old_y):
            x.append(i)
            y.append(j)
            try:
                xm_i, ym_i = midpoint((i, j), midpoint((i, j), (x_mid, y_mid)))

                xm_j, ym_j = midpoint((old_x[c], old_y[c]),
                                      midpoint((old_x[c], old_y[c]),
                                               (x_mid, y_mid)))

                xm, ym = midpoint((xm_i, ym_i), (xm_j, ym_j))
                x.append(xm)
                y.append(ym)
                c += 1
            except IndexError:
                break

        orig_len = len(x)
        x = x[-3:-1] + x + x[1:3]
        y = y[-3:-1] + y + y[1:3]

        t = np.arange(len(x))
        ti = np.linspace(2, orig_len + 1, 10 * orig_len)

        kind = 'quadratic'
        xi = interp1d(t, x, kind=kind)(ti)
        yi = interp1d(t, y, kind=kind)(ti)

        return xi, yi

    def midpoint(p1, p2, sf=1):
        xm = ((p1[0] + p2[0]) / 2) * sf
        ym = ((p1[1] + p2[1]) / 2) * sf
        return (xm, ym)

    num_vars = 6
    centre = 0.5

    theta = np.linspace(0, 2 * np.pi, num_vars, endpoint=False)
    theta += np.pi / 2

    verts = unit_poly_verts(theta, centre)
    xv = [v[0] for v in verts]
    yv = [v[1] for v in verts]

    f1 = df[(df.Protein == str(gpcr1.value)) & (df.Lipids == str(lipid1.value))
            & (df.ResID == int(str(residue1.value).split("-")[1])) &
            (df.Radius == float(
                radius1.value))].loc[:,
                                     list(df.columns)[:6]].to_numpy().reshape(
                                         6, )

    f2 = df[(df.Protein == str(gpcr2.value)) & (df.Lipids == str(lipid2.value))
            & (df.ResID == int(str(residue2.value).split("-")[1])) &
            (df.Radius == float(
                radius2.value))].loc[:,
                                     list(df.columns)[:6]].to_numpy().reshape(
                                         6, )

    flist = [f1, f2]

    p = figure(plot_height=600,
               plot_width=600,
               x_range=(-0.3, 1.3),
               y_range=(-0.3, 1.3),
               tools="")
    cmap = RdBu[6]
    colors = cmap[:1] + cmap[-1:]

    patch1 = ColumnDataSource(data=dict(xi=[], yi=[]))
    circle1 = ColumnDataSource(data=dict(xt=[], yt=[]))
    xt, yt = radar_patch(f1, theta, centre)
    xi, yi = star_curv(xt + xt[:1], yt + yt[:1])
    patch = p.patch(x="xi",
                    y="yi",
                    fill_alpha=0.15,
                    fill_color=colors[0],
                    line_color=colors[0],
                    source=patch1)
    circle = p.circle(x='xt',
                      y='yt',
                      size=10,
                      alpha=0.5,
                      line_color=colors[0],
                      fill_color=colors[0],
                      source=circle1)

    patch2 = ColumnDataSource(data=dict(xi=[], yi=[]))
    circle2 = ColumnDataSource(data=dict(xt=[], yt=[]))
    xt, yt = radar_patch(f2, theta, centre)
    xi, yi = star_curv(xt + xt[:1], yt + yt[:1])
    patch = p.patch(x="xi",
                    y="yi",
                    fill_alpha=0.15,
                    fill_color=colors[1],
                    line_color=colors[1],
                    source=patch2)
    circle = p.circle(x='xt',
                      y='yt',
                      size=10,
                      alpha=0.5,
                      line_color=colors[1],
                      fill_color=colors[1],
                      source=circle2)

    # Draw grid so the plot looks like a polar graph.
    text_label = list(df.columns)[:6] + ['']
    p.circle(x=0.5,
             y=0.5,
             size=20,
             fill_alpha=0,
             line_color='black',
             line_dash='dashed',
             line_alpha=0.2)
    for size in [x * 100 for x in range(1, 10)]:
        p.circle(x=0.5,
                 y=0.5,
                 size=size,
                 fill_alpha=0,
                 line_color='black',
                 line_dash='dashed',
                 line_alpha=0.2)

    line = np.linspace(-2, 2, 100)
    p.line(line, (line * 0.58) + 0.21,
           line_color='black',
           line_dash='dashed',
           line_alpha=0.2)
    p.line(line, (line * (-0.58)) + 0.79,
           line_color='black',
           line_dash='dashed',
           line_alpha=0.2)
    p.line([0.5] * 100,
           line,
           line_color='black',
           line_dash='dashed',
           line_alpha=0.2)

    # Hide axes.
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None
    p.xaxis.major_tick_line_color = None
    p.xaxis.minor_tick_line_color = None
    p.yaxis.major_tick_line_color = None
    p.yaxis.minor_tick_line_color = None
    p.xaxis.major_label_text_font_size = '0pt'
    p.yaxis.major_label_text_font_size = '0pt'

    p.axis.visible = None
    p.toolbar.logo = None
    p.toolbar_location = None

    # Draw the hexagon with labels attached.
    p.line(x=xv + [centre], y=yv + [1], color='black')

    xv[1] = xv[1] - 0.13
    xv[2] = xv[2] - 0.1
    xv[-2] = xv[-2] + 0.16
    xv[-1] = xv[-1] + 0.1
    yv[3] = yv[3] - 0.06

    label_source = ColumnDataSource({
        'x': xv + [centre],
        'y': yv + [1],
        'text': text_label
    })
    labels = LabelSet(x="x",
                      y="y",
                      text="text",
                      source=label_source,
                      level='glyph',
                      text_align="center")
    p.add_layout(labels)

    def select_dfGPCR():
        gpcr1_val, gpcr2_val = gpcr1.value, gpcr2.value
        lipid1_val, lipid2_val = lipid1.value, lipid2.value
        res1_val, res2_val = str(residue1.value).split("-")[1], str(
            residue2.value).split("-")[1]

        f1 = df[(df.Protein == str(gpcr1_val)) & (df.Lipids == str(lipid1_val))
                & (df.ResID == int(res1_val)) &
                (df.Radius == float(radius1.value)
                 )].loc[:, list(df.columns)[:6]].to_numpy().reshape(6, )
        f2 = df[(df.Protein == str(gpcr2_val)) & (df.Lipids == str(lipid2_val))
                & (df.ResID == int(res2_val)) &
                (df.Radius == float(radius2.value)
                 )].loc[:, list(df.columns)[:6]].to_numpy().reshape(6, )

        return (f1, f2)

    def update1():
        gpcr_val = gpcr1.value
        lipid1_val = lipid1.value
        radius1_val = radius1.value

        resname = df[(df.Protein == str(gpcr_val))
                     & (df.Lipids == str(lipid1_val)) &
                     (df.Radius == float(radius1_val))].ResName.to_list()
        resid = df[(df.Protein == str(gpcr_val))
                   & (df.Lipids == str(lipid1_val)) &
                   (df.Radius == float(radius1_val))].ResID.to_list()

        residues = []
        for rn, ri in zip(resname, resid):
            residues.append("{}-{}".format(rn, ri))

        residue1.options = residues
        if residue1.value not in residues:
            residue1.value = residues[0]

        f1 = select_dfGPCR()[0]
        xt, yt = radar_patch(f1, theta, centre)
        xi, yi = star_curv(xt + xt[:1], yt + yt[:1])

        circle1.data = dict(xt=xt, yt=yt)
        patch1.data = dict(xi=xi, yi=yi)

    def update2():
        gpcr_val = gpcr1.value
        lipid2_val = lipid2.value
        radius2_val = radius2.value

        resname = df[(df.Protein == str(gpcr_val))
                     & (df.Lipids == str(lipid2_val)) &
                     (df.Radius == float(radius2_val))].ResName.to_list()
        resid = df[(df.Protein == str(gpcr_val))
                   & (df.Lipids == str(lipid2_val)) &
                   (df.Radius == float(radius2_val))].ResID.to_list()

        residues = []
        for rn, ri in zip(resname, resid):
            residues.append("{}-{}".format(rn, ri))

        # options = [str(x) for x in options]
        residue2.options = residues
        if residue2.value not in residues:
            residue2.value = residues[0]

        f2 = select_dfGPCR()[1]
        xt, yt = radar_patch(f2, theta, centre)
        xi, yi = star_curv(xt + xt[:1], yt + yt[:1])

        circle2.data = dict(xt=xt, yt=yt)
        patch2.data = dict(xi=xi, yi=yi)

    controls1 = [gpcr1, lipid1, residue1, radius1]
    controls2 = [gpcr2, lipid2, residue2, radius2]

    for control1 in controls1:
        control1.on_change('value', lambda attr, old, new: update1())
    for control2 in controls2:
        control2.on_change('value', lambda attr, old, new: update2())

    inputs1 = column([gpcr1, lipid1, residue1, radius1])
    inputs2 = column([gpcr2, lipid2, residue2, radius2])

    l = layout([[inputs1, p, inputs2]])

    update1()
    update2()

    doc.add_root(l)

    doc.title = "Radar App"
Example #11
0
    def distanceApp(doc: Document) -> None:

        distances = lipid_residue_distances[0]
        time = lipid_residue_distances[1]['time']
        proteins = lipid_residue_distances[1]['protein']
        lipids = list(distances.keys())
        residues = list(distances[lipids[0]].keys())
        protein_id = list(distances[lipids[0]][residues[0]].keys())

        residues = [str(x) for x in residues]
        protein_id = [str(x) for x in protein_id]

        source = ColumnDataSource(data=dict(x=[], y=[]))

        protein_name = Select(title="Protein",
                              value=proteins[0],
                              options=proteins,
                              width=100)
        pc = Select(title="Protein Copy",
                    value=protein_id[0],
                    options=protein_id,
                    width=100)
        res = Select(title="Residue Selection",
                     value=residues[0],
                     options=residues,
                     width=100)
        lip = Select(title="Lipid Selection",
                     value=lipids[0],
                     options=lipids,
                     width=100)
        p = figure(plot_width=1500,
                   plot_height=400,
                   tools='pan, box_zoom, ywheel_zoom, save, reset, help')

        color = '#%02x%02x%02x' % tuple(np.random.choice(range(256), size=3))
        p.line(x='x', y='y', line_color=color, source=source, line_width=4)

        p.y_range = Range1d(0, 4)
        p.x_range = Range1d(time[0], time[-1])

        p.toolbar.autohide = True
        p.axis.axis_label_text_font_size = "12pt"
        p.axis.axis_label_text_font_style = "bold"
        p.title.align = 'center'

        p.xaxis.axis_label = "Trajectory Time"
        p.yaxis.axis_label = "Distance (nm)"

        def update():

            protein_selected = protein_name.value
            copy_selected = pc.value
            residue_selected = res.value
            lipid_selected = lip.value

            residues = list(distances[lipid_selected].keys())
            if int(residue_selected) not in residues:
                residue_selected = residues[0]

            res.options = [str(x) for x in residues]

            y = distances[lipid_selected][int(residue_selected)][int(
                copy_selected)]
            source.data = dict(x=time, y=y)

        controls = [protein_name, pc, res, lip]
        for control in controls:
            control.on_change('value', lambda attr, old, new: update())

        inputs2 = row([*controls])
        layout1 = layout([[inputs2]])
        layout2 = layout([p])

        update()

        doc.add_root(layout1)
        doc.add_root(layout2)

        doc.title = "Distance Calculations"
        doc.theme = Theme(json=yaml.load("""
            attrs:
                Figure:
                    toolbar_location: above
                    height: 500
                    width: 1000
                Grid:
                    grid_line_dash: [6, 4]
                    grid_line_color: black
        """,
                                         Loader=yaml.FullLoader))
Example #12
0
def define_plot(
    doc: Document,
    rt_client: _StreamingClient,
    channels: list,
    tribe: RealTimeTribe,
    inventory: Inventory,
    detections: list,
    map_options: dict,
    plot_options: dict,
    plot_length: float,
    update_interval: int,
    data_color: str = "grey",
    lowcut: float = 1.0,
    highcut: float = 10.0,
    offline: bool = False,
):
    """
    Set up a bokeh plot for real-time plotting.

    Defines a moving data stream and a map.

    Parameters
    ----------
    doc
        Bokeh document to edit - usually called as a partial
    rt_client
        RealTimeClient streaming data
    channels
        Channels to plot
    tribe
        Tribe to plot
    inventory
        Inventory to plot
    detections
        Detections to plot - should be a list that is updated in place.
    map_options
        Dictionary of options for the map
    plot_options
        Dictionary of options for plotting in general
    plot_length
        Length of data plot
    update_interval
        Update frequency in seconds
    data_color
        Colour to data stream
    lowcut
        Lowcut for filtering data stream
    highcut
        Highcut for filtering data stream
    offline
        Flag to set time-stamps to data time-stamps if True, else timestamps
        will be real-time
    """
    # Set up the data source
    Logger.info("Getting stream to define plot")
    stream = rt_client.stream.copy().split().detrend()
    if lowcut and highcut:
        stream.filter("bandpass", freqmin=lowcut, freqmax=highcut)
        title = "Streaming data: {0}-{1} Hz bandpass".format(lowcut, highcut)
    elif lowcut:
        stream.filter("highpass", lowcut)
        title = "Streaming data: {0} Hz highpass".format(lowcut)
    elif highcut:
        stream.filter("lowpass", highcut)
        title = "Streaming data: {0} Hz lowpass".format(highcut)
    else:
        title = "Raw streaming data"
    stream.merge()
    Logger.info(f"Have the stream: \n{stream}")

    template_lats, template_lons, template_alphas, template_ids = (
        [], [], [], [])
    for template in tribe:
        try:
            origin = (template.event.preferred_origin() or
                      template.event.origins[0])
        except IndexError:
            continue
        template_lats.append(origin.latitude)
        template_lons.append(origin.longitude % 360)
        template_alphas.append(0)
        template_ids.append(template.event.resource_id.id.split("/")[-1])

    station_lats, station_lons, station_ids = ([], [], [])
    for network in inventory:
        for station in network:
            station_lats.append(station.latitude)
            station_lons.append(station.longitude % 360)
            station_ids.append(station.code)

    # Get plot bounds in web mercator
    Logger.info("Defining map")
    transformer = Transformer.from_crs(
        "epsg:4326", "epsg:3857", always_xy=True)
    try:
        min_lat, min_lon, max_lat, max_lon = (
            min(template_lats + station_lats),
            min(template_lons + station_lons),
            max(template_lats + station_lats),
            max(template_lons + station_lons))
    except ValueError as e:
        Logger.error(e)
        Logger.info("Setting map bounds to NZ")
        min_lat, min_lon, max_lat, max_lon = (-47., 165., -34., 179.9)
    Logger.info(f"Map bounds: {min_lon}, {min_lat} - {max_lon}, {max_lat}")
    bottom_left = transformer.transform(min_lon, min_lat)
    top_right = transformer.transform(max_lon, max_lat)
    map_x_range = (bottom_left[0], top_right[0])
    map_y_range = (bottom_left[1], top_right[1])

    template_x, template_y = ([], [])
    for lon, lat in zip(template_lons, template_lats):
        _x, _y = transformer.transform(lon, lat)
        template_x.append(_x)
        template_y.append(_y)

    station_x, station_y = ([], [])
    for lon, lat in zip(station_lons, station_lats):
        _x, _y = transformer.transform(lon, lat)
        station_x.append(_x)
        station_y.append(_y)

    template_source = ColumnDataSource({
        'y': template_y, 'x': template_x,
        'lats': template_lats, 'lons': template_lons,
        'template_alphas': template_alphas, 'id': template_ids})
    station_source = ColumnDataSource({
        'y': station_y, 'x': station_x,
        'lats': station_lats, 'lons': station_lons, 'id': station_ids})

    Logger.info("Allocated data sources")
    trace_sources = {}
    trace_data_range = {}
    # Allocate empty arrays
    for channel in channels:
        tr = stream.select(id=channel)[0]
        times = np.arange(
            tr.stats.starttime.datetime,
            (tr.stats.endtime + tr.stats.delta).datetime,
            step=dt.timedelta(seconds=tr.stats.delta))
        data = tr.data
        trace_sources.update(
            {channel: ColumnDataSource({'time': times, 'data': data})})
        trace_data_range.update({channel: (data.min(), data.max())})

    # Set up the map to go on the left side
    Logger.info("Adding features to map")
    map_plot = figure(
        title="Template map", x_range=map_x_range, y_range=map_y_range,
        x_axis_type="mercator", y_axis_type="mercator", **map_options)
    url = 'http://a.basemaps.cartocdn.com/rastertiles/voyager/{Z}/{X}/{Y}.png'
    attribution = "Tiles by Carto, under CC BY 3.0. Data by OSM, under ODbL"
    map_plot.add_tile(WMTSTileSource(url=url, attribution=attribution))
    map_plot.circle(
        x="x", y="y", source=template_source, fill_color="firebrick",
        line_color="grey", line_alpha=.2,
        fill_alpha="template_alphas", size=10)
    map_plot.triangle(
        x="x", y="y", size=10, source=station_source, color="blue", alpha=1.0)

    # Set up the trace plots
    Logger.info("Setting up streaming plot")
    trace_plots = []
    if not offline:
        now = dt.datetime.utcnow()
    else:
        now = max([tr.stats.endtime for tr in stream]).datetime
    p1 = figure(
        y_axis_location="right", title=title,
        x_range=[now - dt.timedelta(seconds=plot_length), now],
        plot_height=int(plot_options["plot_height"] * 1.2),
        **{key: value for key, value in plot_options.items()
           if key != "plot_height"})
    p1.yaxis.axis_label = None
    p1.xaxis.axis_label = None
    p1.min_border_bottom = 0
    p1.min_border_top = 0
    if len(channels) != 1:
        p1.xaxis.major_label_text_font_size = '0pt'
    p1_line = p1.line(
        x="time", y='data', source=trace_sources[channels[0]],
        color=data_color, line_width=1)
    legend = Legend(items=[(channels[0], [p1_line])])
    p1.add_layout(legend, 'right')

    datetick_formatter = DatetimeTickFormatter(
        days=["%m/%d"], months=["%m/%d"],
        hours=["%m/%d %H:%M:%S"], minutes=["%m/%d %H:%M:%S"],
        seconds=["%m/%d %H:%M:%S"], hourmin=["%m/%d %H:%M:%S"],
        minsec=["%m/%d %H:%M:%S"])
    p1.xaxis.formatter = datetick_formatter

    # Add detection lines
    Logger.info("Adding detection artists")
    detection_source = _get_pick_times(detections, channels[0])
    detection_source.update(
        {"pick_values": [[
            int(min(stream.select(id=channels[0])[0].data) * .9),
            int(max(stream.select(id=channels[0])[0].data) * .9)]
            for _ in detection_source['picks']]})
    detection_sources = {channels[0]: ColumnDataSource(detection_source)}
    detection_lines = MultiLine(
        xs="picks", ys="pick_values", line_color="red", line_dash="dashed",
        line_width=1)
    p1.add_glyph(detection_sources[channels[0]], detection_lines)

    trace_plots.append(p1)

    if len(channels) > 1:
        for i, channel in enumerate(channels[1:]):
            p = figure(
                x_range=p1.x_range,
                y_axis_location="right", **plot_options)
            p.yaxis.axis_label = None
            p.xaxis.axis_label = None
            p.min_border_bottom = 0
            # p.min_border_top = 0
            p_line = p.line(
                x="time", y="data", source=trace_sources[channel],
                color=data_color, line_width=1)
            legend = Legend(items=[(channel, [p_line])])
            p.add_layout(legend, 'right')
            p.xaxis.formatter = datetick_formatter

            # Add detection lines
            detection_source = _get_pick_times(detections, channel)
            detection_source.update(
                {"pick_values": [[
                    int(min(stream.select(id=channel)[0].data) * .9),
                    int(max(stream.select(id=channel)[0].data) * .9)]
                    for _ in detection_source['picks']]})
            detection_sources.update({
                channel: ColumnDataSource(detection_source)})
            detection_lines = MultiLine(
                xs="picks", ys="pick_values", line_color="red",
                line_dash="dashed", line_width=1)
            p.add_glyph(detection_sources[channel], detection_lines)

            trace_plots.append(p)
            if i != len(channels) - 2:
                p.xaxis.major_label_text_font_size = '0pt'
    plots = gridplot([[map_plot, column(trace_plots)]])

    previous_timestamps = {
        channel: stream.select(id=channel)[0].stats.endtime
        for channel in channels}
    
    def update():
        Logger.debug("Plot updating")
        _stream = rt_client.stream.split().detrend()
        if lowcut and highcut:
            _stream.filter("bandpass", freqmin=lowcut, freqmax=highcut)
        elif lowcut:
            _stream.filter("highpass", lowcut)
        elif highcut:
            _stream.filter("lowpass", highcut)
        _stream.merge()

        for _i, _channel in enumerate(channels):
            try:
                _tr = _stream.select(id=_channel)[0]
            except IndexError:
                Logger.debug("No channel for {0}".format(_channel))
                continue
            new_samples = int(_tr.stats.sampling_rate * (
                    previous_timestamps[_channel] - _tr.stats.endtime))
            if new_samples == 0:
                Logger.debug("No new data for {0}".format(_channel))
                continue
            _new_data = _tr.slice(
                starttime=previous_timestamps[_channel])
            new_times = np.arange(
                _new_data.stats.starttime.datetime,
                (_tr.stats.endtime + _tr.stats.delta).datetime,
                step=dt.timedelta(seconds=_tr.stats.delta))
            new_data = {'time': new_times[1:], 'data': _new_data.data[1:]}
            Logger.debug("Channl: {0}\tNew times: {1}\t New data: {2}".format(
                _tr.id, new_data["time"].shape, new_data["data"].shape))
            trace_sources[_channel].stream(
                new_data=new_data,
                rollover=int(plot_length * _tr.stats.sampling_rate))
            new_picks = _get_pick_times(detections, _channel)
            new_picks.update({
                'pick_values': [
                    [int(np.nan_to_num(
                        trace_sources[_channel].data['data']).max() * .9),
                     int(np.nan_to_num(
                         trace_sources[_channel].data['data']).min() * .9)]
                    for _ in new_picks['picks']]})
            detection_sources[_channel].data = new_picks
            previous_timestamps.update({_channel: _tr.stats.endtime})
            Logger.debug("New data plotted for {0}".format(_channel))
        if not offline:
            now = dt.datetime.utcnow()
        else:
            try:
                now = max([tr.stats.endtime for tr in _stream]).datetime
            except ValueError:
                return
        trace_plots[0].x_range.start = now - dt.timedelta(seconds=plot_length)
        trace_plots[0].x_range.end = now
        _update_template_alphas(
            detections, tribe, decay=plot_length, now=now,
            datastream=template_source)
    Logger.info("Adding callback")
    doc.add_periodic_callback(update, update_interval)
    doc.title = "EQcorrscan Real-time plotter"
    doc.add_root(plots)
    Logger.info("Plot defined")
Example #13
0
def line_handler(doc: Document) -> None:

    task_id = doc.session_context.request.arguments.get('task_id')
    username = doc.session_context.request.arguments.get('username')

    user_dir = os.path.join(settings.USER_DATA, username)
    path_to_db = os.path.join(user_dir, task_id)
    conn = os.path.join(path_to_db, 'distances.p')
    with open(conn, 'rb') as fp:
        lipid_residue_distances = pickle.load(fp)

    # variables
    distances = lipid_residue_distances[0]
    time = lipid_residue_distances[1]['time']
    proteins = lipid_residue_distances[1]['protein']
    lipids = list(distances.keys())
    residues = list(distances[lipids[0]].keys())
    protein_id = list(distances[lipids[0]][residues[0]].keys())
    residues = [str(x) for x in residues]
    protein_id = [str(x) for x in protein_id]

    # columndatasource
    source = ColumnDataSource(data=dict(x=[], y=[]))

    #widgets
    protein_name = Select(title="Protein",
                          value=proteins[0],
                          options=proteins,
                          width=100)
    pc = Select(title="Protein Copy",
                value=protein_id[0],
                options=protein_id,
                width=100)
    res = Select(title="Residue Selection",
                 value=residues[0],
                 options=residues,
                 width=100)
    lip = Select(title="Lipid Selection",
                 value=lipids[0],
                 options=lipids,
                 width=100)
    p = figure(plot_width=1500,
               plot_height=400,
               tools='pan, box_zoom, ywheel_zoom, save, reset, help')

    # line with random color
    color = '#%02x%02x%02x' % tuple(np.random.choice(range(256), size=3))
    p.line(x='x', y='y', line_color=color, source=source, line_width=2)

    # make pretty
    p.y_range = Range1d(0, 4)
    p.x_range = Range1d(time[0], time[-1])
    p.toolbar.autohide = True
    p.axis.axis_label_text_font_size = "12pt"
    p.axis.axis_label_text_font_style = "bold"
    p.title.align = 'center'
    p.xaxis.axis_label = "Trajectory Time"
    p.yaxis.axis_label = "Distance (nm)"

    def update():

        protein_selected = protein_name.value
        copy_selected = pc.value
        residue_selected = res.value
        lipid_selected = lip.value

        residues = list(distances[lipid_selected].keys())
        if int(residue_selected) not in residues:
            residue_selected = residues[0]

        res.options = [str(x) for x in residues]

        y = distances[lipid_selected][int(residue_selected)][int(
            copy_selected)]
        source.data = dict(x=time, y=y)

    # add controls
    controls = [protein_name, pc, res, lip]
    for control in controls:
        control.on_change('value', lambda attr, old, new: update())

    # align plot elements
    inputs2 = row([*controls])
    layout1 = layout([[inputs2]])
    layout2 = layout([p])

    # render
    update()
    doc.add_root(layout1)
    doc.add_root(layout2)
    doc.title = "Distance Calculations"
    doc.theme = Theme(json=yaml.load("""
        attrs:
            Figure:
                toolbar_location: above
                height: 500
                width: 1000
            Grid:
                grid_line_dash: [6, 4]
                grid_line_color: black
    """,
                                     Loader=yaml.FullLoader))