public PepV01(FastaSeqV01 fastaSequence, int begin, int end, int missedCleavages, double mh, double?rt) : this(fastaSequence, begin, end, missedCleavages) { MassH = new TypedMass(mh, MassType.MonoisotopicMassH); PredictedRetentionTime = rt; }
private static CellDesc CreateIon(IonType type, int ordinal, TypedMass massH, Adduct charge, IEnumerable <DocNode> choices, ICollection <DocNode> chosen, Transition tranSelected, RenderTools rt) { double mz = SequenceMassCalc.GetMZ(massH, charge); CellDesc cell = CreateData(string.Format(@"{0:F02}", mz), rt); foreach (TransitionDocNode nodeTran in choices) { Transition tran = nodeTran.Transition; if (tran.IonType == type && tran.Ordinal == ordinal && tran.Adduct == charge) { cell.Font = rt.FontBold; if (Equals(tran, tranSelected)) { cell.Brush = rt.BrushSelected; // Stop after selected break; } if (!chosen.Contains(nodeTran)) { cell.Brush = rt.BrushChoice; // Keep looking } else { cell.Brush = rt.BrushChosen; // Stop after chosen break; } } } return(cell); }
public void TestGetFragmentFormula() { var pepseq = "PEPTIDE"; var sequenceMassCalc = new SequenceMassCalc(MassType.Monoisotopic); var precursor = FragmentedMolecule.EMPTY.ChangeModifiedSequence( new ModifiedSequence(pepseq, new ModifiedSequence.Modification[0], MassType.Monoisotopic)); var peptide = new Peptide(precursor.UnmodifiedSequence); var transitionGroup = new TransitionGroup(peptide, Adduct.SINGLY_PROTONATED, IsotopeLabelType.light); var settings = SrmSettingsList.GetDefault(); var transitionGroupDocNode = new TransitionGroupDocNode(transitionGroup, Annotations.EMPTY, settings, ExplicitMods.EMPTY, null, null, null, new TransitionDocNode[0], false); foreach (var ionType in new[] { IonType.a, IonType.b, IonType.c, IonType.x, IonType.y, IonType.z }) { for (int ordinal = 1; ordinal < pepseq.Length; ordinal++) { var transition = new Transition(transitionGroup, ionType, Transition.OrdinalToOffset(ionType, ordinal, pepseq.Length), 0, Adduct.SINGLY_PROTONATED); var fragment = precursor.ChangeFragmentIon(ionType, ordinal); var actualMassDistribution = FragmentedMolecule.Settings.DEFAULT.GetMassDistribution( fragment.FragmentFormula, 0, 0); var expectedMz = sequenceMassCalc.GetFragmentMass(transition, transitionGroupDocNode.IsotopeDist); if (expectedMz.IsMassH()) { expectedMz = new TypedMass(expectedMz.Value - BioMassCalc.MassProton, expectedMz.MassType & ~MassType.bMassH); } var actualMz = actualMassDistribution.MostAbundanceMass; if (Math.Abs(expectedMz - actualMz) > .001) { Assert.AreEqual(expectedMz, actualMz, .001, "Ion type {0} Ordinal {1}", ionType, ordinal); } } } }
public TransitionDocNode(Transition id, TransitionLosses losses, TypedMass massH, TransitionQuantInfo quantInfo) : this(id, Annotations.EMPTY, losses, massH, quantInfo, null) { }
public TransitionDocNode(Transition id, TransitionLosses losses, TypedMass massH, TransitionQuantInfo quantInfo, ExplicitTransitionValues explicitTransitionValues) : this(id, Annotations.EMPTY, losses, massH, quantInfo, explicitTransitionValues, null) { }
private TransitionDocNode CreateTransitionNode(int massIndex, TypedMass precursorMassH, TransitionIsotopeDistInfo isotopeDistInfo, TransitionLosses losses, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> transitionRanks, CustomMolecule customMolecule = null) { Transition transition = new Transition(this, massIndex, customMolecule); var quantInfo = TransitionDocNode.TransitionQuantInfo.GetLibTransitionQuantInfo(transition, losses, Transition.CalcMass(precursorMassH, losses), transitionRanks).ChangeIsotopeDistInfo(isotopeDistInfo); return(new TransitionDocNode(transition, losses, precursorMassH, quantInfo)); }
public CustomMolecule(string formula, TypedMass monoisotopicMass, TypedMass averageMass, string name, MoleculeAccessionNumbers moleculeAccessionNumbers) { Formula = formula; MonoisotopicMass = monoisotopicMass; AverageMass = averageMass; Name = name ?? string.Empty; AccessionNumbers = moleculeAccessionNumbers ?? MoleculeAccessionNumbers.EMPTY; Validate(); }
private static Adduct CalcProductCharge(TypedMass productMassH, int?productZ, double productMz, double tolerance, bool isCustomIon, Adduct maxCharge, MassShiftType massShiftType, out int massShift, out int nearestCharge) { return(CalcCharge(productMassH, productMz, tolerance, isCustomIon, productZ ?? Transition.MIN_PRODUCT_CHARGE, productZ ?? Math.Min(maxCharge.AdductCharge, Transition.MAX_PRODUCT_CHARGE), Transition.MassShifts, massShiftType, out massShift, out nearestCharge)); }
private TransitionDocNode CreateTransitionNode(int massIndex, TypedMass precursorMassH, TransitionIsotopeDistInfo isotopeDistInfo, TransitionLosses losses, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> transitionRanks, Adduct productAdduct, CustomMolecule customMolecule = null) { Transition transition = new Transition(this, massIndex, productAdduct, customMolecule); var quantInfo = TransitionDocNode.TransitionQuantInfo.GetLibTransitionQuantInfo(transition, losses, Transition.CalcMass(precursorMassH, losses), transitionRanks).ChangeIsotopeDistInfo(isotopeDistInfo); var transitionDocNode = new TransitionDocNode(transition, losses, precursorMassH, quantInfo, ExplicitTransitionValues.EMPTY); if (massIndex < 0) { transitionDocNode = transitionDocNode.ChangeQuantitative(false); } return(transitionDocNode); }
/// <summary> /// Calculates the matching charge within a tolerance for a mass, assuming (de)protonation. /// </summary> /// <param name="mass">The mass to calculate charge for (actually massH if !IsCustomIon)</param> /// <param name="mz">The desired m/z value the charge should produce</param> /// <param name="tolerance">How far off the actual m/z is allowed to be</param> /// <param name="isCustomIon">Is this a custom ion formula?</param> /// <param name="minCharge">Minimum charge to consider</param> /// <param name="maxCharge">Maximum charge to consider</param> /// <param name="massShifts">Possible mass shifts that may have been applied to decoys</param> /// <param name="massShiftType"></param> /// <param name="massShift">Mass shift required to to achieve this charge state or zero</param> /// <param name="nearestCharge">closest matching charge, useful when return value is null</param> /// <returns>A matching charge or null, in which case the closest non-matching charge can be found in the nearestCharge value.</returns> public static Adduct CalcCharge(TypedMass mass, double mz, double tolerance, bool isCustomIon, int minCharge, int maxCharge, ICollection <int> massShifts, MassShiftType massShiftType, out int massShift, out int nearestCharge) { Assume.IsTrue(minCharge <= maxCharge); massShift = 0; nearestCharge = 0; double nearestDelta = double.MaxValue; for (int i = minCharge; i <= maxCharge; i++) { if (i != 0) // Avoid z=0 if we're entertaining negative charge states { double calculatedMz = isCustomIon ? Adduct.FromChargeProtonated(i).MzFromNeutralMass(mass) : SequenceMassCalc.GetMZ(mass, i); double delta = mz - calculatedMz; double deltaAbs = Math.Abs(delta); int potentialShift = (int)Math.Round(deltaAbs); double fractionalDelta = deltaAbs - potentialShift; if (MatchMz(fractionalDelta, tolerance) && MatchMassShift(potentialShift, massShifts, massShiftType)) { massShift = potentialShift; if (delta < 0) { massShift = -massShift; } var result = i; nearestCharge = i; return(Adduct.FromCharge(result, isCustomIon ? Adduct.ADDUCT_TYPE.non_proteomic : Adduct.ADDUCT_TYPE.proteomic)); } if (deltaAbs < nearestDelta) { nearestDelta = deltaAbs; nearestCharge = i; } // If the charge is positive and the calculated m/z is smaller than the desired m/z // increasing the charge further cannot possibly produce a match if (massShiftType == MassShiftType.none && minCharge > 0 && delta > 0) { break; } } } Debug.Assert(nearestCharge != 0); // Could only happen if min > max return(Adduct.EMPTY); }
public static Adduct CalcPrecursorCharge(TypedMass precursorMassH, double precursorMz, double tolerance, bool isCustomIon, bool isDecoy, out int massShift, out int nearestCharge) { return(CalcCharge(precursorMassH, precursorMz, tolerance, isCustomIon, TransitionGroup.MIN_PRECURSOR_CHARGE, TransitionGroup.MAX_PRECURSOR_CHARGE, TransitionGroup.MassShifts, isDecoy ? MassShiftType.shift_only : MassShiftType.none, out massShift, out nearestCharge)); }
private static void CheckLabel(string label) { string unlabel = label.Substring(0, label.Length - 1); var adductLabel = Adduct.DICT_ADDUCT_ISOTOPE_NICKNAMES.FirstOrDefault(x => x.Value == label).Key; var labeled = Adduct.FromStringAssumeProtonated("[2M3C13-Na]"); var unlabeled = Adduct.FromStringAssumeProtonated("[2M-Na]"); var relabeled = Adduct.FromStringAssumeProtonated("[2M3Cl374H2-Na]".Replace("Cl37", adductLabel)); var massNeutral = 5.6; Assert.AreEqual( 2 * (massNeutral + 3 * (BioMassCalc.MONOISOTOPIC.GetMass("C'") - BioMassCalc.MONOISOTOPIC.GetMass("C"))) - BioMassCalc.MONOISOTOPIC.GetMass("Na"), labeled.ApplyToMass(new TypedMass(massNeutral, MassType.Monoisotopic))); Assert.AreEqual(unlabeled, labeled.ChangeIsotopeLabels(null)); var labels = new Dictionary <string, int> { { label, 3 }, { "H2", 4 } }; Assert.AreEqual(relabeled, labeled.ChangeIsotopeLabels(labels)); var labelsToo = new Dictionary <string, int> { { label, 3 }, { "H'", 4 } }; Assert.AreEqual(relabeled, unlabeled.ChangeIsotopeLabels(labelsToo)); var labelsAlso = new Dictionary <string, int> { { adductLabel, 3 }, { "H'", 4 } }; // Mixed Assert.AreEqual(relabeled, unlabeled.ChangeIsotopeLabels(labelsAlso)); Assert.AreNotEqual(labeled, unlabeled.ChangeIsotopeLabels(labelsAlso)); // Check Deuterium and Tritium handling Assert.AreEqual(BioMassCalc.MONOISOTOPIC.GetMass("Cl2Cl'3H5H'4N12"), BioMassCalc.MONOISOTOPIC.GetMass("Cl2Cl'3H5D4N12")); Assert.AreEqual(BioMassCalc.MONOISOTOPIC.GetMass("Cl2Cl'3H5H\"4N12"), BioMassCalc.MONOISOTOPIC.GetMass("Cl2Cl'3H5T4N12")); Assert.AreEqual(Molecule.Parse("Cl2Cl'3H5H'4N12".Replace("Cl'", label).Replace("Cl", unlabel)), Molecule.Parse(relabeled.ApplyIsotopeLabelsToFormula("Cl5H9N12".Replace("Cl", unlabel)))); // Replaces three of five Cl and four of nine H var m100 = new TypedMass(100, MassType.Monoisotopic); var mdiff = 2 * (3 * (BioMassCalc.MONOISOTOPIC.GetMass(label) - BioMassCalc.MONOISOTOPIC.GetMass(unlabel)) + 4 * (BioMassCalc.MONOISOTOPIC.GetMass(BioMassCalc.H2) - BioMassCalc.MONOISOTOPIC.GetMass(BioMassCalc.H))); Assert.AreEqual(m100 + mdiff, relabeled.ApplyIsotopeLabelsToMass(m100), .005); // Expect increase of 2*(3(Cl37-Cl)+4(H2-H)) var isotopeAsMass = Adduct.FromStringAssumeProtonated("[2M1.23-Na]"); Assert.AreEqual(102.46, isotopeAsMass.ApplyIsotopeLabelsToMass(m100), .005); // Expect increase of 2*1.23 }
public CustomIon(string formula, Adduct adduct, TypedMass monoisotopicMass, TypedMass averageMass, string name) : base(formula, monoisotopicMass, averageMass, name) { if (adduct.IsEmpty) { var ionInfo = new IonInfo(NeutralFormula, adduct); // Analyzes the formula to see if it's something like "CH12[M+Na]" if (!Equals(NeutralFormula, ionInfo.NeutralFormula)) { Formula = ionInfo.NeutralFormula; } Adduct = Adduct.FromStringAssumeProtonated(ionInfo.AdductText); } else { Adduct = adduct; } }
public static CustomMolecule FromTSV(string val) { var vals = val.FromEscapedTSV(); var name = vals.Length > 0 ? vals[0] : null; var formula = vals.Length > 1 ? vals[1] : null; // ReSharper disable PossibleNullReferenceException var keysTSV = vals.Length > 2 ? val.Substring(name.Length + formula.Length + 2) : null; // ReSharper restore PossibleNullReferenceException if (formula == null && name != null && name.StartsWith(INVARIANT_NAME_DETAIL)) { // Looks like a mass-only description Regex r = new Regex(massFormatRegex, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant); Match m = r.Match(val); if (m.Success) { try { var massMono = new TypedMass(double.Parse(m.Groups[1].Value, CultureInfo.InvariantCulture), MassType.Monoisotopic); var massAvg = new TypedMass(double.Parse(m.Groups[2].Value, CultureInfo.InvariantCulture), MassType.Average); return(new CustomMolecule(massMono, massAvg)); } catch { Assume.Fail("unable to read custom molecule information"); // Not L10N } } } else if (formula != null && formula.Contains("/")) // Not L10N { // "formula" is actually mono and average masses try { var values = formula.Split('/'); var massMono = new TypedMass(double.Parse(values[0], CultureInfo.InvariantCulture), MassType.Monoisotopic); var massAvg = new TypedMass(double.Parse(values[1], CultureInfo.InvariantCulture), MassType.Average); return(new CustomMolecule(massMono, massAvg, name, new MoleculeAccessionNumbers(keysTSV))); } catch { Assume.Fail("unable to read custom molecule information"); // Not L10N } } return(new CustomMolecule(formula, null, null, name, new MoleculeAccessionNumbers(keysTSV))); }
public FragmentIon(PepV01 peptide, IonType type, int offset, double mh) { _peptide = peptide; IType = type; CleavageOffset = offset; MassH = new TypedMass(mh, MassType.MonoisotopicMassH); // Derived values if (IsNTerminal()) { Ordinal = offset + 1; AA = peptide.Target.Sequence[offset]; } else { Ordinal = _peptide.Length - offset - 1; AA = peptide.Target.Sequence[offset + 1]; } }
/// <summary> /// Calculates the matching charge within a tolerance for a mass, assuming (de)protonation. /// </summary> /// <param name="mass">The mass to calculate charge for (actually massH if !IsCustomIon)</param> /// <param name="mz">The desired m/z value the charge should produce</param> /// <param name="tolerance">How far off the actual m/z is allowed to be</param> /// <param name="isCustomIon">Is this a custom ion formula?</param> /// <param name="minCharge">Minimum charge to consider</param> /// <param name="maxCharge">Maximum charge to consider</param> /// <param name="massShifts">Possible mass shifts that may have been applied to decoys</param> /// <param name="massShiftType"></param> /// <param name="massShift">Mass shift required to to achieve this charge state or zero</param> /// <param name="nearestCharge">closest matching charge, useful when return value is null</param> /// <returns>A matching charge or null, in which case the closest non-matching charge can be found in the nearestCharge value.</returns> public static Adduct CalcCharge(TypedMass mass, double mz, double tolerance, bool isCustomIon, int minCharge, int maxCharge, ICollection <int> massShifts, MassShiftType massShiftType, out int massShift, out int nearestCharge) { Assume.IsTrue(minCharge <= maxCharge); massShift = 0; nearestCharge = 0; double nearestDelta = double.MaxValue; for (int i = minCharge; i <= maxCharge; i++) { if (i != 0) // Avoid z=0 if we're entertaining negative charge states { double delta = mz - (isCustomIon ? Adduct.FromChargeProtonated(i).MzFromNeutralMass(mass) : SequenceMassCalc.GetMZ(mass, i)); double deltaAbs = Math.Abs(delta); int potentialShift = (int)Math.Round(deltaAbs); double fractionalDelta = deltaAbs - potentialShift; if (MatchMz(fractionalDelta, tolerance) && MatchMassShift(potentialShift, massShifts, massShiftType)) { massShift = potentialShift; if (delta < 0) { massShift = -massShift; } var result = i; nearestCharge = i; return(Adduct.FromChargeProtonated(result)); } if (deltaAbs < nearestDelta) { nearestDelta = deltaAbs; nearestCharge = i; } } } Debug.Assert(nearestCharge != 0); // Could only happen if min > max return(Adduct.EMPTY); }
private List <SpectrumPeaksInfo.MI> CalcMIs(TypedMass mass, float[] intensities, int offset) { var result = new List <SpectrumPeaksInfo.MI>(PrositConstants.IONS_PER_RESIDUE / 2); for (var c = 0; c < PrositConstants.IONS_PER_RESIDUE / 2; ++c) { // Not a possible charge if (PeptidePrecursorNCE.NodeGroup.PrecursorCharge <= c) { break; } result.Add(new SpectrumPeaksInfo.MI { Mz = SequenceMassCalc.GetMZ(mass, c + 1), Intensity = intensities[c + offset] }); } return(result); }
public TransitionDocNode(Transition id, Annotations annotations, TransitionLosses losses, TypedMass mass, TransitionQuantInfo transitionQuantInfo, Results <TransitionChromInfo> results) : base(id, annotations) { Losses = losses; if (losses != null) { mass -= losses.Mass; } Mz = id.IsCustom() ? new SignedMz(id.Adduct.MzFromNeutralMass(mass), id.IsNegative()) : new SignedMz(SequenceMassCalc.GetMZ(mass, id.Adduct) + SequenceMassCalc.GetPeptideInterval(id.DecoyMassShift), id.IsNegative()); MzMassType = mass.MassType; IsotopeDistInfo = transitionQuantInfo.IsotopeDistInfo; LibInfo = transitionQuantInfo.LibInfo; Results = results; Quantitative = transitionQuantInfo.Quantititative; }
public static Adduct CalcProductCharge(TypedMass productPrecursorMass, int?productZ, Adduct precursorCharge, IList <IonType> acceptedIonTypes, IonTable <TypedMass> productMasses, IList <IList <ExplicitLoss> > potentialLosses, double productMz, double tolerance, MassType massType, MassShiftType massShiftType, out IonType?ionType, out int?ordinal, out TransitionLosses losses, out int massShift) { // Get length of fragment ion mass array int len = productMasses.GetLength(1); // Check all possible ion types and offsets double?minDelta = null; double?minFragmentMass = null, maxFragmentMass = null, maxLoss = null; if (massShiftType == MassShiftType.none) { if (!productZ.HasValue) { minFragmentMass = productMz - tolerance; } else { minFragmentMass = SequenceMassCalc.GetMH(productMz - tolerance, productZ.Value); maxFragmentMass = SequenceMassCalc.GetMH(productMz + tolerance, productZ.Value); } } var bestCharge = Adduct.EMPTY; IonType? bestIonType = null; int? bestOrdinal = null; TransitionLosses bestLosses = null; int bestMassShift = 0; // Check to see if it is the precursor foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(IonType.precursor, 0, massType, potentialLosses)) { var productMass = productPrecursorMass; if (lossesTrial != null) { productMass -= lossesTrial.Mass; maxLoss = Math.Max(maxLoss ?? 0, lossesTrial.Mass); } int potentialMassShift; int nearestCharge; var charge = CalcProductCharge(productMass, productZ, productMz, tolerance, false, precursorCharge, massShiftType, out potentialMassShift, out nearestCharge); if (Equals(charge, precursorCharge)) { double potentialMz = SequenceMassCalc.GetMZ(productMass, charge) + potentialMassShift; double delta = Math.Abs(productMz - potentialMz); if (CompareIonMatch(delta, lossesTrial, potentialMassShift, minDelta, bestLosses, bestMassShift) < 0) { bestCharge = charge; bestIonType = IonType.precursor; bestOrdinal = len + 1; bestLosses = lossesTrial; bestMassShift = potentialMassShift; minDelta = delta; } } } if (maxLoss.HasValue) { maxFragmentMass += maxLoss.Value; } var categoryLast = -1; foreach (var typeAccepted in GetIonTypes(acceptedIonTypes)) { var type = typeAccepted.IonType; var category = typeAccepted.IonCategory; // Types have priorities. If changing type category, and there is already a // suitable answer stop looking. if (category != categoryLast && minDelta.HasValue && MatchMz(minDelta.Value, tolerance)) { break; } categoryLast = category; // The peptide length is 1 longer than the mass array for (int ord = len; ord > 0; ord--) { int offset = Transition.OrdinalToOffset(type, ord, len + 1); var productMassBase = productMasses[type, offset]; // Until below the maximum fragment mass no possible matches if (maxFragmentMass.HasValue && productMassBase > maxFragmentMass.Value) { continue; } // Once below the minimum fragment mass no more possible matches, so stop if (minFragmentMass.HasValue && productMassBase < minFragmentMass.Value) { break; } foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(type, offset, massType, potentialLosses)) { // Look for the closest match. var productMass = productMassBase; if (lossesTrial != null) { productMass -= lossesTrial.Mass; } int potentialMassShift; int nearestCharge; var chargeFound = CalcProductCharge(productMass, productZ, productMz, tolerance, false, precursorCharge, massShiftType, out potentialMassShift, out nearestCharge); if (!chargeFound.IsEmpty) { var charge = chargeFound; double potentialMz = SequenceMassCalc.GetMZ(productMass, charge) + potentialMassShift; double delta = Math.Abs(productMz - potentialMz); if (CompareIonMatch(delta, lossesTrial, potentialMassShift, minDelta, bestLosses, bestMassShift) < 0) { bestCharge = charge; bestIonType = type; bestOrdinal = ord; bestLosses = lossesTrial; bestMassShift = potentialMassShift; minDelta = delta; } } } } } ionType = bestIonType; ordinal = bestOrdinal; losses = bestLosses; massShift = bestMassShift; return(bestCharge); }
public CustomMolecule(TypedMass monoisotopicMass, TypedMass averageMass, string name = null, MoleculeAccessionNumbers moleculeAccessionNumbers = null) : this(null, monoisotopicMass, averageMass, name, moleculeAccessionNumbers) { }
public IsotopeDistInfo(MassDistribution massDistribution, TypedMass monoisotopicMass, Adduct adduct, Func <double, double> calcFilterWindow, double massResolution, double minimumAbundance) { _monoisotopicMass = monoisotopicMass; _adduct = adduct.Unlabeled; // Don't reapply explicit isotope labels // Get peak center of mass values for the given resolution var q1FilterValues = MassDistribution.NewInstance(massDistribution, massResolution, 0).Keys.ToList(); // Find the monoisotopic m/z and make sure it is exactly the expected number double monoMz = _adduct.MzFromNeutralMass(_monoisotopicMass); double monoMzDist = monoMz; int monoMassIndex = 0; for (int i = 0; i < q1FilterValues.Count; i++) { double peakCenterMz = q1FilterValues[i]; double filterWindow = calcFilterWindow(peakCenterMz); double startMz = peakCenterMz - filterWindow / 2; double endMz = startMz + filterWindow; if (startMz < monoMz && monoMz < endMz) { monoMzDist = q1FilterValues[i]; q1FilterValues[i] = monoMz; monoMassIndex = i; break; } } // Insert a M-1 peak, even if it is not expected in the isotope mass distribution if (monoMassIndex == 0 && q1FilterValues.Count > 1) { // Use the delta from the original distribution monoMz to the next peak q1FilterValues.Insert(0, monoMz + monoMzDist - q1FilterValues[1]); monoMassIndex++; } if (!q1FilterValues.Any()) { // This should never happen, but just in case it does happen, we safely exit the constructor ExpectedPeaks = ImmutableList.Singleton(new MzRankProportion(monoMz, 0, 1.0f)); MonoMassIndex = BaseMassIndex = 0; return; } var signedQ1FilterValues = q1FilterValues.Select(q => new SignedMz(q, adduct.AdductCharge < 0)).ToList(); // Use the filtering algorithm that will be used on real data to determine the // expected proportions of the mass distribution that will end up filtered into // peaks // CONSIDER: Mass accuracy information is not calculated here var key = new PrecursorTextId(signedQ1FilterValues[monoMassIndex], null, null, ChromExtractor.summed); var filter = new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, 0, null, null, false, false); filter.AddQ1FilterValues(signedQ1FilterValues, calcFilterWindow); var expectedSpectrum = filter.FilterQ1SpectrumList(new[] { new MsDataSpectrum { Mzs = massDistribution.Keys.ToArray(), Intensities = massDistribution.Values.ToArray(), NegativeCharge = (adduct.AdductCharge < 0) } }); int startIndex = expectedSpectrum.Intensities.IndexOf(inten => inten >= minimumAbundance); if (startIndex == -1) { // This can happen if the amino acid modifications are messed up, // and the peptide mass is negative or something. ExpectedPeaks = ImmutableList.Singleton(new MzRankProportion(monoMz, 0, 1.0f)); MonoMassIndex = BaseMassIndex = 0; return; } // Always include the M-1 peak, even if it is expected to have zero intensity if (startIndex > monoMassIndex - 1) { startIndex = monoMassIndex - 1; } if (startIndex < 0) { startIndex = 0; } int endIndex = expectedSpectrum.Intensities.LastIndexOf(inten => inten >= minimumAbundance) + 1; int countPeaks = endIndex - startIndex; var listProportionIndices = new List <KeyValuePair <float, int> >(countPeaks); for (int i = 0; i < countPeaks; i++) { listProportionIndices.Add(new KeyValuePair <float, int>( expectedSpectrum.Intensities[i + startIndex], i)); } // Sort proportions descending. listProportionIndices.Sort((p1, p2) => Comparer.Default.Compare(p2.Key, p1.Key)); // Set proportions and ranks back in the original locations var expectedProportionRanks = new KeyValuePair <float, int> [countPeaks]; for (int i = 0; i < countPeaks; i++) { expectedProportionRanks[listProportionIndices[i].Value] = new KeyValuePair <float, int>(listProportionIndices[i].Key, i + 1); } MonoMassIndex = monoMassIndex - startIndex; // Find the base peak and fill in the masses and proportions var expectedPeaks = new List <MzRankProportion>(); for (int i = 0; i < countPeaks; i++) { float expectedProportion = expectedProportionRanks[i].Key; int rank = expectedProportionRanks[i].Value; expectedPeaks.Add(new MzRankProportion(q1FilterValues[i + startIndex], rank, expectedProportion)); if (expectedProportion > expectedProportionRanks[BaseMassIndex].Key) { BaseMassIndex = i; } } ExpectedPeaks = expectedPeaks; }
public static TypedMass CalcMass(TypedMass massH, TransitionLosses losses) { return(massH - (losses != null ? losses.Mass : 0)); }
public void CalcMass(SequenceMassCalc massCalc) { MassH = massCalc.GetPrecursorMass(Target.Sequence); }
public void OkDialog() { var helper = new MessageBoxHelper(this); var charge = 0; if (textCharge.Visible && !helper.ValidateSignedNumberTextBox(textCharge, _minCharge, _maxCharge, out charge)) { return; } var adduct = Adduct.NonProteomicProtonatedFromCharge(charge); if (RetentionTimeWindow.HasValue && !RetentionTime.HasValue) { helper.ShowTextBoxError(textRetentionTimeWindow, Resources .Peptide_ExplicitRetentionTimeWindow_Explicit_retention_time_window_requires_an_explicit_retention_time_value_); return; } if (Adduct.IsEmpty || Adduct.AdductCharge != adduct.AdductCharge) { Adduct = adduct; // Note: order matters here, this settor indirectly updates _formulaBox.MonoMass when formula is empty } if (string.IsNullOrEmpty(_formulaBox.NeutralFormula)) { // Can the text fields be understood as mz? if (!_formulaBox.ValidateAverageText(helper)) { return; } if (!_formulaBox.ValidateMonoText(helper)) { return; } } var monoMass = new TypedMass(_formulaBox.MonoMass ?? 0, MassType.Monoisotopic); var averageMass = new TypedMass(_formulaBox.AverageMass ?? 0, MassType.Average); if (monoMass < CustomMolecule.MIN_MASS || averageMass < CustomMolecule.MIN_MASS) { _formulaBox.ShowTextBoxErrorFormula(helper, string.Format( Resources .EditCustomMoleculeDlg_OkDialog_Custom_molecules_must_have_a_mass_greater_than_or_equal_to__0__, CustomMolecule.MIN_MASS)); return; } if (monoMass > CustomMolecule.MAX_MASS || averageMass > CustomMolecule.MAX_MASS) { _formulaBox.ShowTextBoxErrorFormula(helper, string.Format( Resources .EditCustomMoleculeDlg_OkDialog_Custom_molecules_must_have_a_mass_less_than_or_equal_to__0__, CustomMolecule.MAX_MASS)); return; } if ((_transitionSettings != null) && (!_transitionSettings.IsMeasurablePrecursor( adduct.MzFromNeutralMass(monoMass, MassType.Monoisotopic)) || !_transitionSettings.IsMeasurablePrecursor(adduct.MzFromNeutralMass(averageMass, MassType.Average)))) { _formulaBox.ShowTextBoxErrorFormula(helper, Resources .SkylineWindow_AddMolecule_The_precursor_m_z_for_this_molecule_is_out_of_range_for_your_instrument_settings_); return; } if (_usageMode == UsageMode.precursor) { // Only the adduct should be changing SetResult(_resultCustomMolecule, Adduct); } else if (!string.IsNullOrEmpty(_formulaBox.NeutralFormula)) { try { var name = textName.Text; if (string.IsNullOrEmpty(name)) { name = _formulaBox.NeutralFormula; // Clip off any adduct description } SetResult(new CustomMolecule(_formulaBox.NeutralFormula, name), Adduct); } catch (InvalidDataException x) { _formulaBox.ShowTextBoxErrorFormula(helper, x.Message); return; } } else { SetResult(new CustomMolecule(monoMass, averageMass, textName.Text), Adduct); } // Did user change the list of heavy labels? if (_driverLabelType != null) { PeptideModifications modifications = new PeptideModifications( _peptideSettings.Modifications.StaticModifications, _peptideSettings.Modifications.MaxVariableMods, _peptideSettings.Modifications.MaxNeutralLosses, _driverLabelType.GetHeavyModifications(), // This is the only thing the user may have altered _peptideSettings.Modifications.InternalStandardTypes); var settings = _peptideSettings.ChangeModifications(modifications); // Only update if anything changed if (!Equals(settings, _peptideSettings)) { SrmSettings newSettings = _parent.DocumentUI.Settings.ChangePeptideSettings(settings); if (!_parent.ChangeSettings(newSettings, true)) { return; } _peptideSettings = newSettings.PeptideSettings; } } // See if this combination of charge and label would conflict with any existing transition groups if (_existingIds != null && _existingIds.Any(t => { var transitionGroup = t as TransitionGroup; return(transitionGroup != null && Equals(transitionGroup.LabelType, IsotopeLabelType) && Equals(transitionGroup.PrecursorAdduct.AsFormula(), Adduct .AsFormula()) && // Compare AsFormula so proteomic and non-proteomic protonation are seen as same thing !ReferenceEquals(t, _initialId)); })) { helper.ShowTextBoxError(textName, Resources .EditCustomMoleculeDlg_OkDialog_A_precursor_with_that_adduct_and_label_type_already_exists_, textName.Text); return; } // See if this would conflict with any existing transitions if (_existingIds != null && (_existingIds.Any(t => { var transition = t as Transition; return(transition != null && (Equals(transition.Adduct.AsFormula(), Adduct.AsFormula()) && Equals(transition.CustomIon, ResultCustomMolecule)) && !ReferenceEquals(t, _initialId)); }))) { helper.ShowTextBoxError(textName, Resources.EditCustomMoleculeDlg_OkDialog_A_similar_transition_already_exists_, textName.Text); return; } DialogResult = DialogResult.OK; }
private static void TestEditingTransitionAsMasses() { double massPrecisionTolerance = Math.Pow(10, -SequenceMassCalc.MassPrecision); var doc = SkylineWindow.Document; RunUI(() => { SkylineWindow.ExpandPrecursors(); SkylineWindow.SequenceTree.SelectedNode = SkylineWindow.SequenceTree.Nodes[0].FirstNode.FirstNode.FirstNode; }); var editMoleculeDlg = ShowDialog <EditCustomMoleculeDlg>( () => SkylineWindow.ModifyTransition((TransitionTreeNode)SkylineWindow.SequenceTree.SelectedNode)); var monoMass = new TypedMass(805, MassType.Monoisotopic); RunUI(() => { Assert.AreEqual(BioMassCalc.MONOISOTOPIC.CalculateMassFromFormula(C12H12), editMoleculeDlg.FormulaBox.MonoMass ?? -1, massPrecisionTolerance); Assert.AreEqual(BioMassCalc.AVERAGE.CalculateMassFromFormula(C12H12), editMoleculeDlg.FormulaBox.AverageMass ?? -1, massPrecisionTolerance); Assert.AreEqual(BioMassCalc.CalculateIonMz(BioMassCalc.MONOISOTOPIC.CalculateMassFromFormula(C12H12), editMoleculeDlg.Adduct), double.Parse(editMoleculeDlg.FormulaBox.MonoText), massPrecisionTolerance); Assert.AreEqual(BioMassCalc.CalculateIonMz(BioMassCalc.AVERAGE.CalculateMassFromFormula(C12H12), editMoleculeDlg.Adduct), double.Parse(editMoleculeDlg.FormulaBox.AverageText), massPrecisionTolerance); Assert.AreEqual(Adduct.M_PLUS.AdductFormula, editMoleculeDlg.FormulaBox.Adduct.AdductFormula); editMoleculeDlg.FormulaBox.AverageMass = 800; editMoleculeDlg.FormulaBox.MonoMass = monoMass.Value; editMoleculeDlg.NameText = "Fragment"; }); OkDialog(editMoleculeDlg, editMoleculeDlg.OkDialog); var newdoc = WaitForDocumentChange(doc); Assert.AreEqual("Fragment", newdoc.MoleculeTransitions.ElementAt(0).Transition.CustomIon.ToString()); Assert.AreEqual(BioMassCalc.CalculateIonMz(monoMass, editMoleculeDlg.Adduct), newdoc.MoleculeTransitions.ElementAt(0).Mz, massPrecisionTolerance); Assert.IsFalse(ReferenceEquals(doc.MoleculeTransitions.ElementAt(0).Id, newdoc.MoleculeTransitions.ElementAt(0).Id)); // Changing the mass changes the Id // Verify that tree selection doesn't change just because we changed an ID object // (formerly the tree node would collapse and focus would jump up a level) RunUI(() => { Assert.AreEqual(SkylineWindow.SequenceTree.SelectedNode, SkylineWindow.SequenceTree.Nodes[0].FirstNode.FirstNode.FirstNode); }); // And test undo/redo RunUI(() => SkylineWindow.Undo()); newdoc = WaitForDocumentChange(newdoc); Assert.AreNotEqual("Fragment", newdoc.MoleculeTransitions.ElementAt(0).Transition.CustomIon.ToString()); Assert.AreNotEqual(BioMassCalc.CalculateIonMz(monoMass, editMoleculeDlg.Adduct), newdoc.MoleculeTransitions.ElementAt(0).Mz, massPrecisionTolerance); Assert.IsTrue(ReferenceEquals(doc.MoleculeTransitions.ElementAt(0).Id, newdoc.MoleculeTransitions.ElementAt(0).Id)); RunUI(() => SkylineWindow.Redo()); newdoc = WaitForDocumentChange(newdoc); Assert.AreEqual("Fragment", newdoc.MoleculeTransitions.ElementAt(0).Transition.CustomIon.ToString()); Assert.AreEqual(BioMassCalc.CalculateIonMz(monoMass, editMoleculeDlg.Adduct), newdoc.MoleculeTransitions.ElementAt(0).Mz, massPrecisionTolerance); // Verify that tree selection doesn't change just because we changed an ID object // (formerly the tree node would collapse and focus would jump up a level) RunUI(() => { Assert.AreEqual(SkylineWindow.SequenceTree.SelectedNode, SkylineWindow.SequenceTree.Nodes[0].FirstNode.FirstNode.FirstNode); }); }
public static TransitionQuantInfo GetTransitionQuantInfo(Transition transition, TransitionLosses losses, IsotopeDistInfo isotopeDist, TypedMass massH, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> ranks) { var transitionIsotopeDistInfo = GetIsotopeDistInfo(transition, losses, isotopeDist); return(GetLibTransitionQuantInfo(transition, losses, massH, ranks).ChangeIsotopeDistInfo(transitionIsotopeDistInfo)); }
public static TransitionQuantInfo GetLibTransitionQuantInfo(Transition transition, TransitionLosses losses, TypedMass massH, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> ranks) { LibraryRankedSpectrumInfo.RankedMI rmi = null; if (ranks != null) { ranks.TryGetValue(SequenceMassCalc.GetMZ(massH, transition.Adduct), out rmi); } TransitionLibInfo transitionLibInfo = null; if (rmi != null) { transitionLibInfo = new TransitionLibInfo(rmi.Rank, rmi.Intensity); } return(new TransitionQuantInfo(null, transitionLibInfo, rmi == null || rmi.Quantitative)); }
public static Adduct CalcProductCharge(TypedMass productPrecursorMass, Adduct precursorCharge, IList <IonType> acceptedIonTypes, IonTable <TypedMass> productMasses, IList <IList <ExplicitLoss> > potentialLosses, double productMz, double tolerance, MassType massType, MassShiftType massShiftType, out IonType?ionType, out int?ordinal, out TransitionLosses losses, out int massShift) { // Get length of fragment ion mass array int len = productMasses.GetLength(1); // Check all possible ion types and offsets double? minDelta = null; var bestCharge = Adduct.EMPTY; IonType? bestIonType = null; int? bestOrdinal = null; TransitionLosses bestLosses = null; int bestMassShift = 0; // Check to see if it is the precursor foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(IonType.precursor, 0, massType, potentialLosses)) { var productMass = productPrecursorMass - (lossesTrial != null ? lossesTrial.Mass : 0); int potentialMassShift; int nearestCharge; var charge = CalcProductCharge(productMass, productMz, tolerance, false, precursorCharge, massShiftType, out potentialMassShift, out nearestCharge); if (Equals(charge, precursorCharge)) { double potentialMz = SequenceMassCalc.GetMZ(productMass, charge) + potentialMassShift; double delta = Math.Abs(productMz - potentialMz); if (CompareIonMatch(delta, lossesTrial, potentialMassShift, minDelta, bestLosses, bestMassShift) < 0) { bestCharge = charge; bestIonType = IonType.precursor; bestOrdinal = len + 1; bestLosses = lossesTrial; bestMassShift = potentialMassShift; minDelta = delta; } } } var categoryLast = -1; foreach (var typeAccepted in GetIonTypes(acceptedIonTypes)) { var type = typeAccepted.IonType; var category = typeAccepted.IonCategory; // Types have priorities. If changing type category, and there is already a // suitable answer stop looking. if (category != categoryLast && minDelta.HasValue && MatchMz(minDelta.Value, tolerance)) { break; } categoryLast = category; for (int offset = 0; offset < len; offset++) { foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(type, offset, massType, potentialLosses)) { // Look for the closest match. var productMass = productMasses[type, offset]; if (lossesTrial != null) { productMass -= lossesTrial.Mass; } int potentialMassShift; int nearestCharge; var chargeFound = CalcProductCharge(productMass, productMz, tolerance, false, precursorCharge, massShiftType, out potentialMassShift, out nearestCharge); if (!chargeFound.IsEmpty) { var charge = chargeFound; double potentialMz = SequenceMassCalc.GetMZ(productMass, charge) + potentialMassShift; double delta = Math.Abs(productMz - potentialMz); if (CompareIonMatch(delta, lossesTrial, potentialMassShift, minDelta, bestLosses, bestMassShift) < 0) { bestCharge = charge; bestIonType = type; // The peptide length is 1 longer than the mass array bestOrdinal = Transition.OffsetToOrdinal(type, offset, len + 1); bestLosses = lossesTrial; bestMassShift = potentialMassShift; minDelta = delta; } } } } } ionType = bestIonType; ordinal = bestOrdinal; losses = bestLosses; massShift = bestMassShift; return(bestCharge); }
private TransitionDocNode CreateTransitionNode(IonType type, int cleavageOffset, Adduct charge, TypedMass massH, TransitionLosses losses, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> transitionRanks, CustomMolecule customMolecule = null) { Transition transition = new Transition(this, type, cleavageOffset, 0, charge, null, customMolecule); var info = TransitionDocNode.TransitionQuantInfo.GetLibTransitionQuantInfo(transition, losses, Transition.CalcMass(massH, losses), transitionRanks); return(new TransitionDocNode(transition, losses, massH, info)); }
public void OkDialog() { var helper = new MessageBoxHelper(this); var charge = 0; if (textCharge.Visible && !helper.ValidateSignedNumberTextBox(textCharge, _minCharge, _maxCharge, out charge)) { return; } var adduct = Adduct.NonProteomicProtonatedFromCharge(charge); if (RetentionTimeWindow.HasValue && !RetentionTime.HasValue) { helper.ShowTextBoxError(textRetentionTimeWindow, Resources .Peptide_ExplicitRetentionTimeWindow_Explicit_retention_time_window_requires_an_explicit_retention_time_value_); return; } if (Adduct.IsEmpty || Adduct.AdductCharge != adduct.AdductCharge) { Adduct = adduct; // Note: order matters here, this settor indirectly updates _formulaBox.MonoMass when formula is empty } if (string.IsNullOrEmpty(_formulaBox.NeutralFormula)) { // Can the text fields be understood as mz? if (!_formulaBox.ValidateAverageText(helper)) { return; } if (!_formulaBox.ValidateMonoText(helper)) { return; } } var monoMass = new TypedMass(_formulaBox.MonoMass ?? 0, MassType.Monoisotopic); var averageMass = new TypedMass(_formulaBox.AverageMass ?? 0, MassType.Average); if (monoMass < CustomMolecule.MIN_MASS || averageMass < CustomMolecule.MIN_MASS) { _formulaBox.ShowTextBoxErrorFormula(helper, string.Format( Resources .EditCustomMoleculeDlg_OkDialog_Custom_molecules_must_have_a_mass_greater_than_or_equal_to__0__, CustomMolecule.MIN_MASS)); return; } if (monoMass > CustomMolecule.MAX_MASS || averageMass > CustomMolecule.MAX_MASS) { _formulaBox.ShowTextBoxErrorFormula(helper, string.Format( Resources .EditCustomMoleculeDlg_OkDialog_Custom_molecules_must_have_a_mass_less_than_or_equal_to__0__, CustomMolecule.MAX_MASS)); return; } if ((_transitionSettings != null) && (!_transitionSettings.IsMeasurablePrecursor( adduct.MzFromNeutralMass(monoMass, MassType.Monoisotopic)) || !_transitionSettings.IsMeasurablePrecursor(adduct.MzFromNeutralMass(averageMass, MassType.Average)))) { _formulaBox.ShowTextBoxErrorFormula(helper, Resources .SkylineWindow_AddMolecule_The_precursor_m_z_for_this_molecule_is_out_of_range_for_your_instrument_settings_); return; } // Ion mobility value must have ion mobility units if (textIonMobility.Visible && IonMobility.HasValue) { if (IonMobilityUnits == eIonMobilityUnits.none) { helper.ShowTextBoxError(textIonMobility, Resources.EditCustomMoleculeDlg_OkDialog_Please_specify_the_ion_mobility_units_); comboBoxIonMobilityUnits.Focus(); return; } if (IonMobility.Value == 0 || (IonMobility.Value < 0 && !IonMobilityFilter.AcceptNegativeMobilityValues(IonMobilityUnits))) { helper.ShowTextBoxError(textIonMobility, string.Format(Resources.SmallMoleculeTransitionListReader_ReadPrecursorOrProductColumns_Invalid_ion_mobility_value__0_, IonMobility)); textIonMobility.Focus(); return; } } if (_usageMode == UsageMode.precursor) { // Only the adduct should be changing SetResult(_resultCustomMolecule, Adduct); } else if (!string.IsNullOrEmpty(_formulaBox.NeutralFormula)) { try { var name = textName.Text; if (string.IsNullOrEmpty(name)) { name = _formulaBox.NeutralFormula; // Clip off any adduct description } SetResult(new CustomMolecule(_formulaBox.NeutralFormula, name), Adduct); } catch (InvalidDataException x) { _formulaBox.ShowTextBoxErrorFormula(helper, x.Message); return; } } else { SetResult(new CustomMolecule(monoMass, averageMass, textName.Text), Adduct); } // Did user change the list of heavy labels? if (_driverLabelType != null) { // This is the only thing the user may have altered var newHeavyMods = _driverLabelType.GetHeavyModifications().ToArray(); if (!ArrayUtil.EqualsDeep(newHeavyMods, _peptideSettings.Modifications.HeavyModifications)) { var labelTypes = _peptideSettings.Modifications.InternalStandardTypes.Where(t => newHeavyMods.Any(m => Equals(m.LabelType, t))).ToArray(); if (labelTypes.Length == 0) { labelTypes = new[] { newHeavyMods.First().LabelType } } ; PeptideModifications modifications = new PeptideModifications( _peptideSettings.Modifications.StaticModifications, _peptideSettings.Modifications.MaxVariableMods, _peptideSettings.Modifications.MaxNeutralLosses, newHeavyMods, labelTypes); var settings = _peptideSettings.ChangeModifications(modifications); SrmSettings newSettings = _parent.DocumentUI.Settings.ChangePeptideSettings(settings); if (!_parent.ChangeSettings(newSettings, true)) { // Not expected, since we checked for a change before calling // Otherwise, this is very confusing. The form just refuses to go away // We would prefer to get an unhandled exception and fix this Assume.Fail(); return; } _peptideSettings = newSettings.PeptideSettings; } } // See if this combination of charge and label would conflict with any existing transition groups if (_existingIds != null && _existingIds.Any(t => { var transitionGroup = t as TransitionGroup; return(transitionGroup != null && Equals(transitionGroup.LabelType, IsotopeLabelType) && Equals(transitionGroup.PrecursorAdduct.AsFormula(), Adduct .AsFormula()) && // Compare AsFormula so proteomic and non-proteomic protonation are seen as same thing !ReferenceEquals(t, _initialId)); })) { helper.ShowTextBoxError(textName, Resources .EditCustomMoleculeDlg_OkDialog_A_precursor_with_that_adduct_and_label_type_already_exists_, textName.Text); return; } // See if this would conflict with any existing transitions if (_existingIds != null && (_existingIds.Any(t => { var transition = t as Transition; return(transition != null && (Equals(transition.Adduct.AsFormula(), Adduct.AsFormula()) && Equals(transition.CustomIon, ResultCustomMolecule)) && !ReferenceEquals(t, _initialId)); }))) { helper.ShowTextBoxError(textName, Resources.EditCustomMoleculeDlg_OkDialog_A_similar_transition_already_exists_, textName.Text); return; } DialogResult = DialogResult.OK; }