def annotate_scan(scan, products, nperrow=4, ax=None): if ax is None: figure = plt.figure() else: figure = ax.figure n = len(products) if n > 0: gs = gridspec.GridSpec(1 + max(int(math.ceil(n / float(nperrow))), 1), nperrow) else: gs = gridspec.GridSpec(1 + (n / nperrow), nperrow) ax = figure.add_subplot(gs[0, :]) if scan.is_profile: draw_raw(scan.arrays, ax=ax) if scan.peak_set is None: scan.pick_peaks() draw_peaklist(scan.peak_set, ax=ax, lw=0.5, alpha=0.75) if scan.deconvoluted_peak_set: draw_peaklist(scan.deconvoluted_peak_set, ax=ax, lw=0.5, alpha=0.75) ax.set_title(scan.id) k = -1 # for the ith row of the grid for i in range(int(n // nperrow) + 1): # for the jth column of the row for j in range(nperrow): # the kth MS^n scan k += 1 try: product_scan = products[k] except IndexError: # the number of MS^n scans is not a multiple of nperrow # so the last row has fewer than nperrow break # add the subplot from the grid spec using i + 1 instead of i # because the MS1 scan is drawn across the row at i = 0 ax = figure.add_subplot(gs[i + 1, j]) if scan.is_profile: draw_raw(scan.arrays, ax=ax, alpha=0.8) # obtain the interval around the precursor pinfo = product_scan.precursor_information if not product_scan.isolation_window.is_empty(): lower, upper = (product_scan.isolation_window.lower_bound - 2, product_scan.isolation_window.upper_bound + 2) else: lower = pinfo.mz - 4 upper = pinfo.mz + 4 try: peak = max(scan.peak_set.between(lower + 1.2, upper - 1.2), key=lambda x: x.intensity) local_intensity = peak.intensity except ValueError: local_intensity = 1e3 # get the monoisotopic peak for the precursor, or the isolation center depending # upon whether the precursor has been deconvoluted and what the instrument reports if pinfo.extracted_charge != 0: target_mz = pinfo.extracted_mz else: target_mz = pinfo.mz draw_peaklist(scan.peak_set, ax=ax, alpha=0.5, lw=0.5) if scan.deconvoluted_peak_set: draw_peaklist(scan.deconvoluted_peak_set.between(lower - 1.2, upper + 1.2, use_mz=True), ax=ax, alpha=0.9, color='blue') ax.set_ylim(0, local_intensity * 1.25) ax.set_xlim(lower, upper) upper_intensity = local_intensity # draw the precursor isolation annotations ax.vlines(target_mz, 0, upper_intensity * 1.5, alpha=0.50, color='red', lw=1) if product_scan.isolation_window.lower != 0: ax.vlines(product_scan.isolation_window.lower_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) if product_scan.isolation_window.upper != 0: ax.vlines(product_scan.isolation_window.upper_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) ax.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) ax.set_ylabel("") ax.set_xlabel("") if pinfo.extracted_charge == 0: if pinfo.charge == "ChargeNotProvided": charge = '?' else: charge = str(pinfo.charge) else: charge = str(pinfo.extracted_charge) ax.set_title("%0.3f @ %s" % (target_mz, charge)) fig = figure # this should probably be a function of figwidth and number of rows fig.set_figheight(fig.get_figheight() * 2) fig.tight_layout() return ax
def annotate_scan(scan, products, nperrow=4, ax=None, label=True): '''Given an MS1 :class:`~.ScanBase` ``scan`` and a :class:`~.Sequence` of :class:`~.ScanBase` product scans, draw the MS1 spectrum in full profile, and then in a subplot grid below it, draw a zoomed-in view of the MS1 spectrum surrounding the area around each precursor ion that gave rise to the scans in ``products``, with monoisotopic peaks and isolation windows marked. .. plot:: :include-source: import ms_deisotope from ms_deisotope import plot from ms_deisotope.test.common import datafile reader = ms_deisotope.MSFileLoader(datafile("20150710_3um_AGP_001_29_30.mzML.gz")) bunch = next(reader) bunch.precursor.pick_peaks() bunch.precursor.deconvolute( scorer=ms_deisotope.PenalizedMSDeconVFitter(20., 2.0), averagine=ms_deisotope.glycopeptide, use_quick_charge=True) ax = plot.annotate_scan(bunch.precursor, bunch.products, nperrow=2) ax.figure.set_figwidth(12) ax.figure.set_figheight(16) Parameters ---------- scan: ScanBase The precursor MS1 scan products: :class:`~.Sequence` of :class:`~.ScanBase` The collection of MSn scans based upon ``scan`` nperrow: int The number of precursor ion subplots to draw per row of the grid. Defaults to :const:`4`. ax: :class:`matplotlib._axes.Axes` An :class:`~.Axes` object to use to find the figure to draw the plot on. Returns ------- :class:`matplotlib._axes.Axes`: The axes of the full MS1 profile plot ''' if ax is None: figure = plt.figure() else: figure = ax.figure n = len(products) if n > 0: gs = gridspec.GridSpec(1 + max(int(math.ceil(n / float(nperrow))), 1), nperrow) else: gs = gridspec.GridSpec(1 + (n / nperrow), nperrow) ax = figure.add_subplot(gs[0, :]) if scan.is_profile: draw_raw(scan.arrays, ax=ax) if scan.peak_set is None: scan.pick_peaks() draw_peaklist(scan.peak_set, ax=ax, lw=0.5, alpha=0.75) if scan.deconvoluted_peak_set: draw_peaklist(scan.deconvoluted_peak_set, ax=ax, lw=0.5, alpha=0.75) ax.set_title(scan.id) k = -1 # for the ith row of the grid for i in range(int(n // nperrow) + 1): # for the jth column of the row for j in range(nperrow): # the kth MS^n scan k += 1 try: product_scan = products[k] except IndexError: # the number of MS^n scans is not a multiple of nperrow # so the last row has fewer than nperrow break # add the subplot from the grid spec using i + 1 instead of i # because the MS1 scan is drawn across the row at i = 0 ax = figure.add_subplot(gs[i + 1, j]) if scan.is_profile: draw_raw(scan.arrays, ax=ax, alpha=0.8) # obtain the interval around the precursor pinfo = product_scan.precursor_information if not product_scan.isolation_window.is_empty(): lower, upper = (product_scan.isolation_window.lower_bound - 2, product_scan.isolation_window.upper_bound + 2) else: lower = pinfo.mz - 4 upper = pinfo.mz + 4 try: peak = max(scan.peak_set.between(lower - 1.2, upper + 1.2), key=lambda x: x.intensity) local_intensity = peak.intensity except ValueError: if scan.deconvoluted_peak_set: try: peak = max(scan.deconvoluted_peak_set.between(lower - 1.2, upper + 1.2, use_mz=True), key=lambda x: x.intensity) local_intensity = peak.intensity except ValueError: local_intensity = 1e3 else: local_intensity = 1e3 # get the monoisotopic peak for the precursor, or the isolation center depending # upon whether the precursor has been deconvoluted and what the instrument reports if pinfo.extracted_charge != 0: target_mz = pinfo.extracted_mz else: target_mz = pinfo.mz draw_peaklist(scan.peak_set, ax=ax, alpha=0.5, lw=0.5) if scan.deconvoluted_peak_set: draw_peaklist( scan.deconvoluted_peak_set.between( lower - 1.2, upper + 1.2, use_mz=True), ax=ax, alpha=0.9, color='blue') if label: label_peaks(scan, lower, upper, ax=ax, is_deconvoluted=bool(scan.deconvoluted_peak_set)) ax.set_ylim(0, local_intensity * 1.25) ax.set_xlim(lower, upper) upper_intensity = local_intensity # draw the precursor isolation annotations ax.vlines(target_mz, 0, upper_intensity * 1.5, alpha=0.50, color='red', lw=1) if product_scan.isolation_window.lower != 0: ax.vlines(product_scan.isolation_window.lower_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) if product_scan.isolation_window.upper != 0: ax.vlines(product_scan.isolation_window.upper_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) ax.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) ax.set_ylabel("") ax.set_xlabel("") if pinfo.extracted_charge == 0: if pinfo.charge == "ChargeNotProvided": charge = '?' else: charge = str(pinfo.charge) else: charge = str(pinfo.extracted_charge) ax.set_title("%0.3f @ %s" % (target_mz, charge)) fig = figure # this should probably be a function of figwidth and number of rows fig.set_figheight(fig.get_figheight() * 2) fig.tight_layout() return ax
def annotate_scan_single(scan, product_scan, ax=None, standalone=True): if ax is None: fig, ax = plt.subplots(1) if scan.is_profile: draw_raw(scan.arrays, ax=ax) if scan.peak_set is None: scan.pick_peaks() draw_peaklist(scan.peak_set, ax=ax, lw=0.5, alpha=0.75) if scan.deconvoluted_peak_set: draw_peaklist(scan.deconvoluted_peak_set, ax=ax, lw=0.5, alpha=0.75) pinfo = product_scan.precursor_information if not product_scan.isolation_window.is_empty(): lower, upper = (product_scan.isolation_window.lower_bound - 2, product_scan.isolation_window.upper_bound + 2) else: lower = pinfo.mz - 4 upper = pinfo.mz + 4 peak_set = scan.peak_set try: peak = max(peak_set.between(lower + 1.2, upper - 1.2), key=lambda x: x.intensity) local_intensity = peak.intensity except ValueError: local_intensity = 1e3 # get the monoisotopic peak for the precursor, or the isolation center depending # upon whether the precursor has been deconvoluted and what the instrument reports if pinfo.extracted_charge != 0: target_mz = pinfo.extracted_mz else: target_mz = pinfo.mz draw_peaklist(scan.peak_set, ax=ax, alpha=0.5, lw=0.5) if scan.deconvoluted_peak_set: draw_peaklist(scan.deconvoluted_peak_set.between(lower - 1.2, upper + 1.2, use_mz=True), ax=ax, alpha=0.9, color='blue') ax.set_ylim(0, local_intensity * 1.25) ax.set_xlim(lower, upper) upper_intensity = local_intensity # draw the precursor isolation annotations ax.vlines(target_mz, 0, upper_intensity * 1.5, alpha=0.50, color='red', lw=1) if product_scan.isolation_window.lower != 0: ax.vlines(product_scan.isolation_window.lower_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) if product_scan.isolation_window.upper != 0: ax.vlines(product_scan.isolation_window.upper_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) ax.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) ax.set_ylabel("") ax.set_xlabel("") if pinfo.extracted_charge == 0: if pinfo.charge == "ChargeNotProvided": charge = '?' else: charge = str(pinfo.charge) else: charge = str(pinfo.extracted_charge) ax.set_title("%0.3f @ %s" % (target_mz, charge)) return ax
def label_peaks(scan, min_mz=None, max_mz=None, ax=None, is_deconvoluted=None, threshold=None, **kwargs): """Label a region of the peak list, marking centroids with their m/z or mass. If the peaks of `scan` have been deconvoluted, the most abundant peak will be annotated with "<neutral mass> (<charge>)", otherwise just "<m/z>". Parameters ---------- scan : :class:`~.ScanBase` The scan to annotate min_mz : float, optional The minimum m/z to annotate max_mz : float, optional The maximum m/z to annotate ax: :class:`matplotlib._axes.Axes` An :class:`~.Axes` object to draw the plot on is_deconvoluted : bool, optional Whether or not to always use :attr:`Scan.deconvoluted_peak_set` threshold : float, optional The intensity threshold under which peaks will be ignored Returns ------- ax: :class:`matplotlib._axes.Axes` The axes the plot was drawn on annotations: :class:`list` of :class:`matplotlib.text.Text` The list of :class:`matplotlib.text.Text` annotations """ if ax is None: # when no axes are provided, draw all the peak data _, ax = plt.subplots(1) if scan.is_profile: draw_raw(scan, ax) if scan.peak_set is not None: draw_peaklist(scan.peak_set, ax) if scan.deconvoluted_peak_set is not None: draw_peaklist(scan.deconvoluted_peak_set, ax) if is_deconvoluted is None: is_deconvoluted = scan.deconvoluted_peak_set is not None if min_mz is None: min_mz = 0 if max_mz is None: if is_deconvoluted: max_mz = max(peak.mz for peak in scan.deconvoluted_peak_set) else: max_mz = max(peak.mz for peak in scan.peak_set) annotations = [] # select the peak sub range if is_deconvoluted: subset = scan.deconvoluted_peak_set.between( min_mz, max_mz, use_mz=True) else: subset = scan.peak_set.between( min_mz, max_mz) if not subset: return # guess the threshold if threshold is None: threshold = 0.0 if is_deconvoluted: threshold_list = ([max(i.intensity for i in p.envelope) for p in subset]) else: threshold_list = ([p.intensity for p in subset]) if threshold_list: threshold = np.mean(threshold_list) threshold_list = [v > threshold for v in threshold_list] if threshold_list: threshold = np.mean(threshold_list) # draw the actual labels kwargs.setdefault("clip_on", True) kwargs.setdefault("fontsize", 10) if is_deconvoluted: for peak in subset: if peak.intensity > threshold: label = '%0.2f (%d)' % (peak.neutral_mass, peak.charge) # set the y-position to the highest peak in the isotopic # pattern pt = max(peak.envelope, key=lambda x: x.intensity) y = pt.intensity * 1.05 # set the x-position to the weighted average m/z in the # isotopic pattern x = np.average( [p.mz for p in peak.envelope], weights=[p.intensity for p in peak.envelope]) annotations.append( ax.text(x, y, label, ha='center', **kwargs)) else: for peak in subset: if peak.intensity > threshold: label = "%0.2f" % (peak.mz, ) y = peak.intensity * 1.05 x = peak.mz annotations.append( ax.text(x, y, label, ha='center', **kwargs)) return annotations, ax
def annotate_scan_single(scan, product_scan, ax=None, label=True, standalone=True): '''Draw a zoomed-in view of the MS1 spectrum ``scan`` surrounding the area around each precursor ion that gave rise to ``product_scan`` with monoisotopic peaks and isolation windows marked. .. plot:: :include-source: import ms_deisotope from ms_deisotope import plot from ms_deisotope.test.common import datafile reader = ms_deisotope.MSFileLoader(datafile("20150710_3um_AGP_001_29_30.mzML.gz")) bunch = next(reader) bunch.precursor.pick_peaks() bunch.precursor.deconvolute( scorer=ms_deisotope.PenalizedMSDeconVFitter(20., 2.0), averagine=ms_deisotope.glycopeptide, use_quick_charge=True) ax = plot.annotate_scan_single(bunch.precursor, bunch.products[0]) ax.figure.set_figwidth(12) Parameters ---------- scan: ScanBase The MS1 scan to annotate product_scan: ScanBase The product scan to annotate the precursor ion of ax: :class:`matplotlib._axes.Axes` An :class:`~.Axes` object to draw the plot on Returns ------- :class:`matplotlib._axes.Axes` ''' if ax is None: _, ax = plt.subplots(1) if scan.is_profile: draw_raw(scan.arrays, ax=ax) if scan.peak_set is None: scan.pick_peaks() draw_peaklist(scan.peak_set, ax=ax, lw=0.5, alpha=0.75) if scan.deconvoluted_peak_set: draw_peaklist(scan.deconvoluted_peak_set, ax=ax, lw=0.5, alpha=0.75) pinfo = product_scan.precursor_information if not product_scan.isolation_window.is_empty(): lower, upper = (product_scan.isolation_window.lower_bound - 2, product_scan.isolation_window.upper_bound + 2) else: lower = pinfo.mz - 4 upper = pinfo.mz + 4 peak_set = scan.peak_set try: peak = max(peak_set.between(lower - 1.2, upper + 1.2), key=lambda x: x.intensity) local_intensity = peak.intensity except ValueError: if scan.deconvoluted_peak_set: try: peak = max(scan.deconvoluted_peak_set.between(lower - 1.2, upper + 1.2, use_mz=True), key=lambda x: x.intensity) local_intensity = peak.intensity except ValueError: local_intensity = 1e3 else: local_intensity = 1e3 # get the monoisotopic peak for the precursor, or the isolation center depending # upon whether the precursor has been deconvoluted and what the instrument reports if pinfo.extracted_charge != 0: target_mz = pinfo.extracted_mz else: target_mz = pinfo.mz draw_peaklist(scan.peak_set, ax=ax, alpha=0.5, lw=0.5) if scan.deconvoluted_peak_set: draw_peaklist( scan.deconvoluted_peak_set.between( lower - 1.2, upper + 1.2, use_mz=True), ax=ax, alpha=0.9, color='blue') if label: label_peaks(scan, lower, upper, ax=ax, is_deconvoluted=bool(scan.deconvoluted_peak_set)) ax.set_ylim(0, local_intensity * 1.25) ax.set_xlim(lower, upper) upper_intensity = local_intensity # draw the precursor isolation annotations ax.vlines(target_mz, 0, upper_intensity * 1.5, alpha=0.50, color='red', lw=1) if product_scan.isolation_window.lower != 0: ax.vlines(product_scan.isolation_window.lower_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) if product_scan.isolation_window.upper != 0: ax.vlines(product_scan.isolation_window.upper_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) ax.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) ax.set_ylabel("") ax.set_xlabel("") if pinfo.extracted_charge == 0: if pinfo.charge == "ChargeNotProvided": charge = '?' else: charge = str(pinfo.charge) else: charge = str(pinfo.extracted_charge) ax.set_title("%0.3f @ %s" % (target_mz, charge)) return ax
def annotate_scan(scan, products, nperrow=4, ax=None, label=True): '''Given an MS1 :class:`~.ScanBase` ``scan`` and a :class:`~.Sequence` of :class:`~.ScanBase` product scans, draw the MS1 spectrum in full profile, and then in a subplot grid below it, draw a zoomed-in view of the MS1 spectrum surrounding the area around each precursor ion that gave rise to the scans in ``products``, with monoisotopic peaks and isolation windows marked. .. plot:: :include-source: import ms_deisotope from ms_deisotope import plot from ms_deisotope.test.common import datafile reader = ms_deisotope.MSFileLoader(datafile("20150710_3um_AGP_001_29_30.mzML.gz")) bunch = next(reader) bunch.precursor.pick_peaks() bunch.precursor.deconvolute( scorer=ms_deisotope.PenalizedMSDeconVFitter(20., 2.0), averagine=ms_deisotope.glycopeptide, use_quick_charge=True) ax = plot.annotate_scan(bunch.precursor, bunch.products, nperrow=2) ax.figure.set_figwidth(12) ax.figure.set_figheight(16) Parameters ---------- scan: ScanBase The precursor MS1 scan products: :class:`~.Sequence` of :class:`~.ScanBase` The collection of MSn scans based upon ``scan`` nperrow: int The number of precursor ion subplots to draw per row of the grid. Defaults to :const:`4`. ax: :class:`matplotlib._axes.Axes` An :class:`~.Axes` object to use to find the figure to draw the plot on. Returns ------- :class:`matplotlib._axes.Axes`: The axes of the full MS1 profile plot ''' if ax is None: figure = plt.figure() else: figure = ax.figure n = len(products) if n > 0: gs = gridspec.GridSpec(1 + max(int(math.ceil(n / float(nperrow))), 1), nperrow) else: gs = gridspec.GridSpec(1 + (n / nperrow), nperrow) ax = figure.add_subplot(gs[0, :]) if scan.is_profile: draw_raw(scan.arrays, ax=ax) if scan.peak_set is None: scan.pick_peaks() draw_peaklist(scan.peak_set, ax=ax, lw=0.5, alpha=0.75) if scan.deconvoluted_peak_set: draw_peaklist(scan.deconvoluted_peak_set, ax=ax, lw=0.5, alpha=0.75) ax.set_title(scan.id) k = -1 # for the ith row of the grid for i in range(int(n // nperrow) + 1): # for the jth column of the row for j in range(nperrow): # the kth MS^n scan k += 1 try: product_scan = products[k] except IndexError: # the number of MS^n scans is not a multiple of nperrow # so the last row has fewer than nperrow break # add the subplot from the grid spec using i + 1 instead of i # because the MS1 scan is drawn across the row at i = 0 ax = figure.add_subplot(gs[i + 1, j]) if scan.is_profile: draw_raw(scan.arrays, ax=ax, alpha=0.8) # obtain the interval around the precursor pinfo = product_scan.precursor_information if not product_scan.isolation_window.is_empty(): lower, upper = (product_scan.isolation_window.lower_bound - 2, product_scan.isolation_window.upper_bound + 2) else: lower = pinfo.mz - 4 upper = pinfo.mz + 4 try: peak = max(scan.peak_set.between(lower + 1.2, upper - 1.2), key=lambda x: x.intensity) local_intensity = peak.intensity except ValueError: local_intensity = 1e3 # get the monoisotopic peak for the precursor, or the isolation center depending # upon whether the precursor has been deconvoluted and what the instrument reports if pinfo.extracted_charge != 0: target_mz = pinfo.extracted_mz else: target_mz = pinfo.mz draw_peaklist(scan.peak_set, ax=ax, alpha=0.5, lw=0.5) if scan.deconvoluted_peak_set: draw_peaklist( scan.deconvoluted_peak_set.between( lower - 1.2, upper + 1.2, use_mz=True), ax=ax, alpha=0.9, color='blue') if label: label_peaks(scan, lower, upper, ax=ax, is_deconvoluted=bool(scan.deconvoluted_peak_set)) ax.set_ylim(0, local_intensity * 1.25) ax.set_xlim(lower, upper) upper_intensity = local_intensity # draw the precursor isolation annotations ax.vlines(target_mz, 0, upper_intensity * 1.5, alpha=0.50, color='red', lw=1) if product_scan.isolation_window.lower != 0: ax.vlines(product_scan.isolation_window.lower_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) if product_scan.isolation_window.upper != 0: ax.vlines(product_scan.isolation_window.upper_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) ax.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) ax.set_ylabel("") ax.set_xlabel("") if pinfo.extracted_charge == 0: if pinfo.charge == "ChargeNotProvided": charge = '?' else: charge = str(pinfo.charge) else: charge = str(pinfo.extracted_charge) ax.set_title("%0.3f @ %s" % (target_mz, charge)) fig = figure # this should probably be a function of figwidth and number of rows fig.set_figheight(fig.get_figheight() * 2) fig.tight_layout() return ax
def annotate_scan_single(scan, product_scan, ax=None, label=True, standalone=True): '''Draw a zoomed-in view of the MS1 spectrum ``scan`` surrounding the area around each precursor ion that gave rise to ``product_scan`` with monoisotopic peaks and isolation windows marked. .. plot:: :include-source: import ms_deisotope from ms_deisotope import plot from ms_deisotope.test.common import datafile reader = ms_deisotope.MSFileLoader(datafile("20150710_3um_AGP_001_29_30.mzML.gz")) bunch = next(reader) bunch.precursor.pick_peaks() bunch.precursor.deconvolute( scorer=ms_deisotope.PenalizedMSDeconVFitter(20., 2.0), averagine=ms_deisotope.glycopeptide, use_quick_charge=True) ax = plot.annotate_scan_single(bunch.precursor, bunch.products[0]) ax.figure.set_figwidth(12) Parameters ---------- scan: ScanBase The MS1 scan to annotate product_scan: ScanBase The product scan to annotate the precursor ion of ax: :class:`matplotlib._axes.Axes` An :class:`~.Axes` object to draw the plot on Returns ------- :class:`matplotlib._axes.Axes` ''' if ax is None: _, ax = plt.subplots(1) if scan.is_profile: draw_raw(scan.arrays, ax=ax) if scan.peak_set is None: scan.pick_peaks() draw_peaklist(scan.peak_set, ax=ax, lw=0.5, alpha=0.75) if scan.deconvoluted_peak_set: draw_peaklist(scan.deconvoluted_peak_set, ax=ax, lw=0.5, alpha=0.75) pinfo = product_scan.precursor_information if not product_scan.isolation_window.is_empty(): lower, upper = (product_scan.isolation_window.lower_bound - 2, product_scan.isolation_window.upper_bound + 2) else: lower = pinfo.mz - 4 upper = pinfo.mz + 4 peak_set = scan.peak_set try: peak = max(peak_set.between(lower + 1.2, upper - 1.2), key=lambda x: x.intensity) local_intensity = peak.intensity except ValueError: local_intensity = 1e3 # get the monoisotopic peak for the precursor, or the isolation center depending # upon whether the precursor has been deconvoluted and what the instrument reports if pinfo.extracted_charge != 0: target_mz = pinfo.extracted_mz else: target_mz = pinfo.mz draw_peaklist(scan.peak_set, ax=ax, alpha=0.5, lw=0.5) if scan.deconvoluted_peak_set: draw_peaklist( scan.deconvoluted_peak_set.between( lower - 1.2, upper + 1.2, use_mz=True), ax=ax, alpha=0.9, color='blue') if label: label_peaks(scan, lower, upper, ax=ax, is_deconvoluted=bool(scan.deconvoluted_peak_set)) ax.set_ylim(0, local_intensity * 1.25) ax.set_xlim(lower, upper) upper_intensity = local_intensity # draw the precursor isolation annotations ax.vlines(target_mz, 0, upper_intensity * 1.5, alpha=0.50, color='red', lw=1) if product_scan.isolation_window.lower != 0: ax.vlines(product_scan.isolation_window.lower_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) if product_scan.isolation_window.upper != 0: ax.vlines(product_scan.isolation_window.upper_bound, 0, upper_intensity * 1.5, linestyle='--', alpha=0.5) ax.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) ax.set_ylabel("") ax.set_xlabel("") if pinfo.extracted_charge == 0: if pinfo.charge == "ChargeNotProvided": charge = '?' else: charge = str(pinfo.charge) else: charge = str(pinfo.extracted_charge) ax.set_title("%0.3f @ %s" % (target_mz, charge)) return ax