Interactive Plots#

With special plotting libraries like holoviews and datashader for big data visualization as well as bokeh for interactiveness, we can use the functionality of pyOpenMS to quickly create fully interactive views of mass spectrometry data. Here we plot a full map of MS1 that can be interactively zoomed-in if you execute the code in a notebook (e.g. on Binder, see the button on top of the page).

 1import pyopenms as oms
 2import pandas as pd
 3import numpy as np
 4import datashader as ds
 5import holoviews as hv
 6import holoviews.operation.datashader as hd
 7from holoviews.plotting.util import process_cmap
 8from holoviews import opts, dim
 9import sys
10
11hv.extension("bokeh")
12
13exp = oms.MSExperiment()  # type: PeakMap
14loader = oms.MzMLFile()
15loadopts = loader.getOptions()  # type: PeakFileOptions
16loadopts.setMSLevels([1])
17loadopts.setSkipXMLChecks(True)
18loadopts.setIntensity32Bit(True)
19loadopts.setIntensityRange(oms.DRange1(oms.DPosition1(5000), oms.DPosition1(sys.maxsize)))
20loader.setOptions(loadopts)
21loader.load("../../../src/data/BSA1.mzML", exp)
22exp.updateRanges()
23expandcols = ["RT", "mz", "inty"]
24spectraarrs2d = exp.get2DPeakDataLong(
25    exp.getMinRT(), exp.getMaxRT(), exp.getMinMZ(), exp.getMaxMZ()
26)
27spectradf = pd.DataFrame(dict(zip(expandcols, spectraarrs2d)))
28spectradf = spectradf.set_index(["RT", "mz"])
29
30maxrt = spectradf.index.get_level_values(0).max()
31minrt = spectradf.index.get_level_values(0).min()
32maxmz = spectradf.index.get_level_values(1).max()
33minmz = spectradf.index.get_level_values(1).min()
34
35
36def new_bounds_hook(plot, elem):
37    x_range = plot.state.x_range
38    y_range = plot.state.y_range
39    x_range.bounds = minrt, maxrt
40    y_range.bounds = minmz, maxmz
41
42
43points = hv.Points(
44    spectradf, kdims=["RT", "mz"], vdims=["inty"], label="MS1 survey scans"
45).opts(
46    fontsize={"title": 16, "labels": 14, "xticks": 6, "yticks": 12},
47    color=np.log(dim("int")),
48    colorbar=True,
49    cmap="Magma",
50    width=1000,
51    height=1000,
52    tools=["hover"],
53)
54
55raster = (
56    hd.rasterize(
57        points,
58        cmap=process_cmap("blues", provider="bokeh"),
59        aggregator=ds.sum("inty"),
60        cnorm="log",
61        alpha=10,
62        min_alpha=0,
63    )
64    .opts(active_tools=["box_zoom"], tools=["hover"], hooks=[new_bounds_hook])
65    .opts(  # weird.. I have no idea why one has to do this. But with one opts you will get an error
66        plot=dict(
67            width=800,
68            height=800,
69            xlabel="Retention time (s)",
70            ylabel="mass/charge (Da)",
71        )
72    )
73)
74
75hd.dynspread(raster, threshold=0.7, how="add", shape="square")

Result:

../_images/bokehms1.png

With this you can also easily create whole dashboards like the one hosted here on a Binder instance. If you are reading/executing this on Binder already, execute the next cell to get a link to your current instance.

1import os
2from IPython.display import Markdown as md
3
4md(
5    "When you are in binder already, you can quickly open the app [here]({}/msbokehapps).".format(
6        os.getenv("JUPYTERHUB_SERVICE_PREFIX")
7    )
8)