def test_graph_deconvolution(self): scan = self.make_scan() scan.pick_peaks() self.assertIsNotNone(scan.peak_set) algorithm_type = CompositionListPeakDependenceGraphDeconvoluter decon_config = { "composition_list": self.compositions, "scorer": PenalizedMSDeconVFitter(5., 2.), "use_subtraction": True } deconresult = deconvolute_peaks(scan.peak_set, decon_config, charge_range=(-1, -8), deconvoluter_type=algorithm_type) dpeaks = deconresult.peak_set n_cases = sum(map(len, self.charges)) # assert len(dpeaks) == n_cases if not (len(dpeaks) == n_cases): tids, ions = self.make_tids() tids, ions = zip( *sorted(zip(tids, ions), key=lambda x: x[0].monoisotopic_mz)) seen = set() for i, dp in enumerate(sorted(dpeaks, key=lambda x: x.mz)): ix = self.get_nearest_index(dp.mz, tids) logger.warning("%0.3f %d %0.3f %r (Matched %d)", dp.neutral_mass, dp.charge, dp.score, dp.solution, ix) seen.add(ix) indices = set(range(len(ions))) missed = list(indices - seen) deconvoluter = algorithm_type(scan.peak_set.clone(), **decon_config) for ix in missed: tid = deconvoluter.generate_theoretical_isotopic_cluster( *ions[ix]) assert np.isclose(sum(p.intensity for p in tid), 1.0) monoisotopic_peak = deconvoluter.peaklist.has_peak( tid[0].mz, 2e-5) if monoisotopic_peak is not None: tid = deconvoluter.recalibrate_theoretical_mz( tid, monoisotopic_peak.mz) eid = deconvoluter.match_theoretical_isotopic_distribution( tid.peaklist, 2e-5) missed_peaks = count_placeholders(eid) deconvoluter.scale_theoretical_distribution(tid, eid) score = deconvoluter.scorer.evaluate(deconvoluter.peaklist, eid, tid.peaklist) fit_record = deconvoluter.fit_composition_at_charge(*ions[ix]) eid = fit_record.experimental tid = fit_record.theoretical rep_eid = drop_placeholders(eid) validation = (len(rep_eid) < 2), ( len(rep_eid) < len(tid) / 2.), (len(rep_eid) == 1 and fit_record.charge > 1) composition, charge = ions[ix] logger.warning( "Missed %r %d (%d missed peaks, score = %0.3f, record = %r, validation = %r)" % (composition, charge, missed_peaks, score, fit_record, validation)) assert not missed
def test_retrieve_deconvolution_solution(self): bunch = self.make_scan() scan = bunch.precursor scan.pick_peaks() ms1_deconvolution_args = { "averagine": glycopeptide, "scorer": PenalizedMSDeconVFitter(20., 2.), } priorities = [] for product in bunch.products: priorities.append(scan.has_peak(product.precursor_information.mz)) algorithm_type = AveraginePeakDependenceGraphDeconvoluter deconresult = deconvolute_peaks(scan.peak_set, ms1_deconvolution_args, priority_list=priorities, deconvoluter_type=algorithm_type) dpeaks = deconresult.peak_set deconvoluter = deconresult.deconvoluter priority_results = deconresult.priorities reference_deconvoluter = algorithm_type(scan.peak_set.clone(), **ms1_deconvolution_args) for i, result in enumerate(priority_results): query = priorities[i].mz if result is None: logger.warn("Query %d (%f) had no result", i, query) raw_peaks = scan.peak_set.between(query - 2, query + 3) anchor_peak = scan.peak_set.has_peak(query) deconvoluted_peaks = dpeaks.between(query - 2, query + 3, use_mz=True) possible_solutions = reference_deconvoluter._fit_all_charge_states( anchor_peak) sols = [] logger.warn("Possible Solutions %r", possible_solutions) if not possible_solutions: for charge in [3, 4, 5]: tid = reference_deconvoluter.averagine.isotopic_cluster( anchor_peak.mz, charge) assert np.isclose(tid.monoisotopic_mz, anchor_peak.mz) assert np.isclose(sum(p.intensity for p in tid), 1.0) eid = reference_deconvoluter.match_theoretical_isotopic_distribution( tid.peaklist, error_tolerance=2e-5) assert len(eid) == len(tid) record = reference_deconvoluter._evaluate_theoretical_distribution( eid, tid, anchor_peak, charge) sols.append(record) logger.warn("Manually Generated Solutions %r", sols) assert anchor_peak is not None and raw_peaks and ( possible_solutions or sols) and not deconvoluted_peaks assert deconvoluter.peak_dependency_network.find_solution_for( anchor_peak) is not None assert dpeaks.has_peak(query, use_mz=True) # error out assert result is not None else: assert 0 <= abs(result.mz - query) < 1 anchor_peak = scan.peak_set.has_peak(query) assert deconvoluter.peak_dependency_network.find_solution_for( anchor_peak) is not None
def test_retrieve_deconvolution_solution(self): bunch = self.make_scan() scan = bunch.precursor scan.pick_peaks() ms1_deconvolution_args = { "averagine": glycopeptide, "scorer": PenalizedMSDeconVFitter(20., 2.), } priorities = [] for product in bunch.products: priorities.append(scan.has_peak(product.precursor_information.mz)) algorithm_type = AveraginePeakDependenceGraphDeconvoluter deconresult = deconvolute_peaks( scan.peak_set, ms1_deconvolution_args, priority_list=priorities, deconvoluter_type=algorithm_type) dpeaks = deconresult.peak_set deconvoluter = deconresult.deconvoluter priority_results = deconresult.priorities reference_deconvoluter = algorithm_type(scan.peak_set.clone(), **ms1_deconvolution_args) for i, result in enumerate(priority_results): query = priorities[i].mz if result is None: logger.warn("Query %d (%f) had no result", i, query) raw_peaks = scan.peak_set.between(query - 2, query + 3) anchor_peak = scan.peak_set.has_peak(query) deconvoluted_peaks = dpeaks.between(query - 2, query + 3, use_mz=True) possible_solutions = reference_deconvoluter._fit_all_charge_states(anchor_peak) sols = [] logger.warn("Possible Solutions %r", possible_solutions) if not possible_solutions: for charge in [3, 4, 5]: tid = reference_deconvoluter.averagine.isotopic_cluster( anchor_peak.mz, charge) assert np.isclose(tid.monoisotopic_mz, anchor_peak.mz) assert np.isclose(sum(p.intensity for p in tid), 1.0) eid = reference_deconvoluter.match_theoretical_isotopic_distribution( tid.peaklist, error_tolerance=2e-5) assert len(eid) == len(tid) record = reference_deconvoluter._evaluate_theoretical_distribution( eid, tid, anchor_peak, charge) sols.append(record) logger.warn("Manually Generated Solutions %r", sols) assert anchor_peak is not None and raw_peaks and (possible_solutions or sols) and not deconvoluted_peaks assert deconvoluter.peak_dependency_network.find_solution_for(anchor_peak) is not None assert dpeaks.has_peak(query, use_mz=True) # error out assert result is not None else: assert 0 <= abs(result.mz - query) < 1 anchor_peak = scan.peak_set.has_peak(query) assert deconvoluter.peak_dependency_network.find_solution_for(anchor_peak) is not None
def test_deconvolution(self): scan = self.make_scan() algorithm_type = AveragineDeconvoluter deconresult = deconvolute_peaks( scan.peak_set, { "averagine": peptide, "scorer": PenalizedMSDeconVFitter(5., 1.), "use_subtraction": False, }, left_search_limit=3, deconvoluter_type=algorithm_type) dpeaks = deconresult.peak_set assert len(dpeaks) == 6 for point in points: peak = dpeaks.has_peak(neutral_mass(point[0], point[1])) self.assertIsNotNone(peak)
def test_deconvolution(self): scan = self.make_scan() algorithm_type = AveragineDeconvoluter deconresult = deconvolute_peaks( scan.peak_set, { "averagine": peptide, "scorer": PenalizedMSDeconVFitter(5., 1.), "use_subtraction": False }, deconvoluter_type=algorithm_type) dpeaks = deconresult.peak_set assert len(dpeaks) == 6 for point in points: peak = dpeaks.has_peak(neutral_mass(point[0], point[1])) self.assertIsNotNone(peak)
def test_graph_deconvolution(self): scan = self.make_scan() scan.pick_peaks() self.assertIsNotNone(scan.peak_set) algorithm_type = CompositionListPeakDependenceGraphDeconvoluter decon_config = { "composition_list": self.compositions, "scorer": PenalizedMSDeconVFitter(5., 2.), "use_subtraction": True } deconresult = deconvolute_peaks( scan.peak_set, decon_config, charge_range=(-1, -8), deconvoluter_type=algorithm_type) dpeaks = deconresult.peak_set n_cases = sum(map(len, self.charges)) # assert len(dpeaks) == n_cases if not (len(dpeaks) == n_cases): tids, ions = self.make_tids() tids, ions = zip(*sorted(zip(tids, ions), key=lambda x: x[0].monoisotopic_mz)) seen = set() for i, dp in enumerate(sorted(dpeaks, key=lambda x: x.mz)): ix = self.get_nearest_index(dp.mz, tids) logger.warning("%0.3f %d %0.3f %r (Matched %d)", dp.neutral_mass, dp.charge, dp.score, dp.solution, ix) seen.add(ix) indices = set(range(len(ions))) missed = list(indices - seen) deconvoluter = algorithm_type(scan.peak_set.clone(), **decon_config) for ix in missed: tid = deconvoluter.generate_theoretical_isotopic_cluster(*ions[ix]) assert np.isclose(sum(p.intensity for p in tid), 1.0) monoisotopic_peak = deconvoluter.peaklist.has_peak(tid[0].mz, 2e-5) if monoisotopic_peak is not None: tid = deconvoluter.recalibrate_theoretical_mz(tid, monoisotopic_peak.mz) eid = deconvoluter.match_theoretical_isotopic_distribution( tid.peaklist, 2e-5) missed_peaks = count_placeholders(eid) deconvoluter.scale_theoretical_distribution(tid, eid) score = deconvoluter.scorer.evaluate(deconvoluter.peaklist, eid, tid.peaklist) fit_record = deconvoluter.fit_composition_at_charge(*ions[ix]) eid = fit_record.experimental tid = fit_record.theoretical rep_eid = drop_placeholders(eid) validation = (len(rep_eid) < 2), (len(rep_eid) < len(tid) / 2.), ( len(rep_eid) == 1 and fit_record.charge > 1) composition, charge = ions[ix] logger.warning("Missed %r %d (%d missed peaks, score = %0.3f, record = %r, validation = %r)" % ( composition, charge, missed_peaks, score, fit_record, validation)) assert not missed
def test_graph_deconvolution(self): scan = self.make_scan() scan.pick_peaks() self.assertIsNotNone(scan.peak_set) algorithm_type = AveraginePeakDependenceGraphDeconvoluter deconresult = deconvolute_peaks( scan.peak_set, { "averagine": peptide, "scorer": PenalizedMSDeconVFitter(5., 1.) }, deconvoluter_type=algorithm_type) dpeaks = deconresult.peak_set deconvoluter = deconresult.deconvoluter for point in points: peak = dpeaks.has_peak(neutral_mass(point[0], point[1])) self.assertIsNotNone(peak) fp = scan.has_peak(peak.mz) self.assertAlmostEqual( deconvoluter.peak_dependency_network.find_solution_for(fp).mz, peak.mz, 3)
def test_graph_deconvolution(self): scan = self.make_scan() scan.pick_peaks() self.assertIsNotNone(scan.peak_set) algorithm_type = AveraginePeakDependenceGraphDeconvoluter deconresult = deconvolute_peaks( scan.peak_set, { "averagine": peptide, "scorer": PenalizedMSDeconVFitter(5., 1.) }, deconvoluter_type=algorithm_type) dpeaks = deconresult.peak_set assert len(dpeaks) == 2 deconvoluter = deconresult.deconvoluter for point in points: peak = dpeaks.has_peak(neutral_mass(point[0], point[1])) self.assertIsNotNone(peak) fp = scan.has_peak(peak.mz) self.assertAlmostEqual( deconvoluter.peak_dependency_network.find_solution_for(fp).mz, peak.mz, 3)
def deconvolute(self, *args, **kwargs): """A wrapper around :func:`ms_deisotope.deconvolution.deconvolute_peaks`. The scan must have had its peaks picked before it can be deconvoluted. Parameters ---------- decon_config : dict, optional Parameters to use to initialize the deconvoluter instance produced by ``deconvoluter_type`` charge_range : tuple of integers, optional The range of charge states to consider. error_tolerance : float, optional PPM error tolerance to use to match experimental to theoretical peaks priority_list : list, optional The set of peaks to target for deconvolution to be able to enforce external constraints on, such as selected precursors for fragmentation. left_search_limit : int, optional The maximum number of neutron shifts to search to the left (decrease) from each query peak right_search_limit : int, optional The maximum number of neutron shifts to search to the right (increase) from each query peak left_search_limit_for_priorities : int, optional The maximum number of neutron shifts to search to the left (decrease) from each query peak for priority targets right_search_limit_for_priorities : None, optional The maximum number of neutron shifts to search to the right (increase) from each query peak for priority targets charge_carrier : float, optional The mass of the charge carrier. Defaults to PROTON truncate_after : float, optional The percentage of the isotopic pattern to include. Defaults to TRUNCATE_AFTER deconvoluter_type : type or callable, optional A callable returning a deconvoluter. Defaults to :class:`~.AveraginePeakDependenceGraphDeconvoluter` **kwargs Additional keywords passed to :func:`~.deconvolute_peaks` Returns ------- Scan Returns self Raises ------ ValueError If :attr:`peak_set` is None, a :class:`ValueError` will be raised indicating that a scan must be centroided before it can be deconvoluted See Also -------- :func:`~.deconvolute_peaks` """ if self.peak_set is None: raise ValueError("Cannot deconvolute a scan that has not been " "centroided. Call `pick_peaks` first.") charge_range = kwargs.get("charge_range", (1, 8)) if self.polarity < 0 and max(charge_range) > 0: charge_range = tuple(c * self.polarity for c in charge_range) kwargs['charge_range'] = charge_range decon_results = deconvolute_peaks(self.peak_set, *args, **kwargs) self.deconvoluted_peak_set = decon_results.peak_set return self
def deconvolute(self, *args, **kwargs): """A wrapper around :func:`ms_deisotope.deconvolution.deconvolute_peaks`. The scan must have had its peaks picked before it can be deconvoluted. Parameters ---------- decon_config : dict, optional Parameters to use to initialize the deconvoluter instance produced by ``deconvoluter_type`` charge_range : tuple of integers, optional The range of charge states to consider. error_tolerance : float, optional PPM error tolerance to use to match experimental to theoretical peaks priority_list : list, optional The set of peaks to target for deconvolution to be able to enforce external constraints on, such as selected precursors for fragmentation. left_search_limit : int, optional The maximum number of neutron shifts to search to the left (decrease) from each query peak right_search_limit : int, optional The maximum number of neutron shifts to search to the right (increase) from each query peak left_search_limit_for_priorities : int, optional The maximum number of neutron shifts to search to the left (decrease) from each query peak for priority targets right_search_limit_for_priorities : None, optional The maximum number of neutron shifts to search to the right (increase) from each query peak for priority targets charge_carrier : float, optional The mass of the charge carrier. Defaults to PROTON truncate_after : float, optional The percentage of the isotopic pattern to include. Defaults to TRUNCATE_AFTER deconvoluter_type : type or callable, optional A callable returning a deconvoluter. Defaults to :class:`~.AveraginePeakDependenceGraphDeconvoluter` **kwargs Additional keywords passed to :func:`~.deconvolute_peaks` Returns ------- Scan Returns self Raises ------ ValueError If :attr:`peak_set` is None, a :class:`ValueError` will be raised indicating that a scan must be centroided before it can be deconvoluted See Also -------- :func:`~.deconvolute_peaks` """ if self.peak_set is None: raise ValueError("Cannot deconvolute a scan that has not been " "centroided. Call `pick_peaks` first.") charge_range = kwargs.get("charge_range", (1, 8)) if self.polarity < 0 and max(charge_range) > 0: charge_range = tuple(c * self.polarity for c in charge_range) kwargs['charge_range'] = charge_range decon_results = deconvolute_peaks(self.peak_set, *args, **kwargs) self.deconvoluted_peak_set = decon_results.peak_set return self