Source code for ms_peak_picker.plot

'''A collection of tools for drawing and annotating mass spectra
'''
from collections import namedtuple

from matplotlib import pyplot as plt
import numpy as np


from .base import PeakLike


point = namedtuple('point', ('mz', 'intensity'))


[docs]def draw_raw(mz_array, intensity_array=None, ax=None, normalize=False, **kwargs): """Draws un-centroided profile data, visualizing continuous data points Parameters ---------- mz_array : :class:`np.ndarray` or :class:`tuple` Either the m/z array to be visualized, or if `intensity_array` is `None`, `mz_array` will be unpacked, looking to find a sequence of two `np.ndarray` objects for the m/z (X) and intensity (Y) coordinates intensity_array : :class:`np.ndarray`, optional The intensity array to be visualized. If `None`, will attempt to unpack `mz_array` ax : :class:`matplotlib.Axes`, optional The axis to draw the plot on. If missing, a new one will be created using :func:`matplotlib.pyplot.subplots` normalize: bool, optional if `True`, will normalize the abundance dimension to be between 0 and 100% pretty: bool, optional If `True`, will call :func:`_beautify_axes` on `ax` **kwargs Passed to :meth:`matplotlib.Axes.plot` Returns ------- :class:`~.Axes` """ pretty = kwargs.pop("pretty", True) if intensity_array is None and len(mz_array) == 2: mz_array, intensity_array = mz_array if ax is None: _, ax = plt.subplots(1) if normalize: intensity_array = intensity_array / intensity_array.max() * 100.0 ax.plot(mz_array, intensity_array, **kwargs) ax.set_xlabel("m/z") ax.set_ylabel("Relative Intensity") if pretty: if intensity_array.shape[0] > 0: set_ylim = intensity_array.min() >= 0 else: set_ylim = True _beautify_axes(ax, set_ylim, normalize) return ax
def peaklist_to_vector(peaklist, width=0.000001): """Convert a list of discrete centroided peaks into a pair of continuous m/z and intensity arrays Parameters ---------- peaklist : :class:`~Iterable` of :class:`~.PeakLike` The collection of peaks to convert width : float, optional The spacing between the center of the peak and it's shoulders Returns ------- np.ndarray: The generated m/z array np.ndarray: The generated intensity array Raises ------ TypeError When the input could not be coerced into a peak list """ try: mzs = [] intensities = [] for peak in sorted(peaklist, key=lambda x: x.mz): mzs.append(peak.mz - width) intensities.append(0.) mzs.append(peak.mz) intensities.append(peak.intensity) mzs.append(peak.mz + width) intensities.append(0.) return np.array(mzs), np.array(intensities) except AttributeError: pt = peaklist[0] if not PeakLike.is_a(pt): try: if len(pt) == 2: peaklist = [point(*p) for p in peaklist] return peaklist_to_vector(peaklist, width) except Exception: pass raise TypeError("Expected a sequence of peak-like objects" " or (mz, intensity) pairs, but got %r instead" % type(pt))
[docs]def draw_peaklist(peaklist, ax=None, normalize=False, **kwargs): """Draws centroided peak data, visualizing peak apexes. The peaks will be converted into a single smooth curve using :func:`peaklist_to_vector`. Parameters ---------- peaklist: :class:`Iterable` of :class:`~.PeakLike` The peaks to draw. ax : matplotlib.Axes, optional The axis to draw the plot on. If missing, a new one will be created using :func:`matplotlib.pyplot.subplots` normalize: bool, optional if `True`, will normalize the abundance dimension to be between 0 and 100% pretty: bool, optional If `True`, will call :func:`_beautify_axes` on `ax` **kwargs Passed to :meth:`matplotlib.Axes.plot` Returns ------- matplotlib.Axes """ pretty = kwargs.pop("pretty", True) if ax is None: _, ax = plt.subplots(1) mz_array, intensity_array = peaklist_to_vector(peaklist) if normalize: intensity_array = intensity_array / intensity_array.max() * 100.0 ax.plot(mz_array, intensity_array, **kwargs) ax.set_xlabel("m/z") ax.set_ylabel("Relative Intensity") if pretty: if intensity_array.shape[0] > 0: set_ylim = intensity_array.min() >= 0 else: set_ylim = True _beautify_axes(ax, set_ylim, normalize) return ax
def mirror_peaks(peaklist1, peaklist2, ax=None, normalize=True, kwargs1=None, kwargs2=None, **kwargs): """Create a mirror plot of two peak lists. Plot one peak list upside-down below another peak list. Commonly used to compare/contrast two two peak lists visually. Parameters ---------- peaklist1 : :class:`~.Iterable` The peak list to plot right-side up. peaklist2 : :class:`~.Iterable` The peak list to plot upside-down. ax : matplotlib.Axes, optional The axis to draw the plot on. If missing, a new one will be created using :func:`matplotlib.pyplot.subplots` normalize : bool, optional Whether or not to normalize the intensity scales of the spectra. The default is :const:`True`, unlike other drawing functions, in order to keep the scales of the spectra relatively equal. kwargs1 : dict, optional Any keyword arguments to be applied solely when drawing `peaklist1`. kwargs2 : dict, optional Any keyword arguments to be applied solely when drawing `peaklist2`. pretty: bool, optional If `True`, will call :func:`_beautify_axes` on `ax` **kwargs: Keyword arguments to be used when drawing both peak lists. Passed to :meth:`matplotlib.Axes.plot` Returns ------- :class:`matplotlib.Axes` """ pretty = kwargs.pop("pretty", True) if kwargs1 is None: kwargs1 = {} if kwargs2 is None: kwargs2 = {} if ax is None: _, ax = plt.subplots(1) # Draw first peak list mz_array, intensity_array = peaklist_to_vector(peaklist1) if normalize: intensity_array = intensity_array / intensity_array.max() * 100.0 kwargs1.update(kwargs) ax.plot(mz_array, intensity_array, **kwargs1) # Draw second peak list mz_array, intensity_array = peaklist_to_vector(peaklist2) if normalize: intensity_array = intensity_array / intensity_array.max() * 100.0 intensity_array = -1 * intensity_array kwargs2.update(kwargs) ax.plot(mz_array, intensity_array, **kwargs2) # Update the axes if needed. if pretty: _beautify_axes(ax, False) _normalize_ylabels(ax, adjust_sign=True) return ax def _beautify_axes(ax, set_ylim=True, normalize=False): ax.axes.spines['right'].set_visible(False) ax.axes.spines['top'].set_visible(False) ax.yaxis.tick_left() ax.xaxis.tick_bottom() ax.xaxis.set_ticks_position('none') ax.get_xaxis().get_major_formatter().set_useOffset(False) if set_ylim: ax.set_ylim(0, max(ax.get_ylim())) if normalize: _normalize_ylabels(ax) return ax def _normalize_ylabels(ax, adjust_sign=True): ytick_labels = ax.get_yticklabels() yticks = ax.get_yticks() for tl, tick in zip(ytick_labels, yticks): txt = tl.get_text() if txt == "": txt = str(tick) if adjust_sign: txt = txt.replace("-", "") txt += "%" tl.set_text(txt) ax.set_yticklabels(ytick_labels) return ax __all__ = [ "draw_peaklist", "draw_raw" ]