Esempio n. 1
0
 public void Validate()
 {
     if (!string.IsNullOrEmpty(Formula))
     {
         try
         {
             MonoisotopicMass = SequenceMassCalc.FormulaMass(BioMassCalc.MONOISOTOPIC, Formula);
             AverageMass      = SequenceMassCalc.FormulaMass(BioMassCalc.AVERAGE, Formula);
         }
         catch (ArgumentException x)
         {
             throw new InvalidDataException(x.Message, x);  // Pass original as inner exception
         }
     }
     if (AverageMass == 0 || MonoisotopicMass == 0)
     {
         throw new InvalidDataException(Resources.CustomMolecule_Validate_Custom_molecules_must_specify_a_formula_or_valid_monoisotopic_and_average_masses_);
     }
     if (AverageMass > MAX_MASS || MonoisotopicMass > MAX_MASS)
     {
         throw new InvalidDataException(string.Format(Resources.CustomMolecule_Validate_The_mass__0__of_the_custom_molecule_exceeeds_the_maximum_of__1__,
                                                      AverageMass > MAX_MASS ? AverageMass : MonoisotopicMass, MAX_MASS));
     }
     if (AverageMass < MIN_MASS || MonoisotopicMass < MIN_MASS)
     {
         throw new InvalidDataException(string.Format(Resources.CustomMolecule_Validate_The_mass__0__of_the_custom_molecule_is_less_than_the_minimum_of__1__,
                                                      AverageMass < MIN_MASS ? AverageMass : MonoisotopicMass, MIN_MASS));
     }
 }
Esempio n. 2
0
        public static Modification MakeModification(string unmodifiedSequence, ExplicitMod explicitMod)
        {
            var staticMod = explicitMod.Modification;
            int i         = explicitMod.IndexAA;
            var monoMass  = staticMod.MonoisotopicMass ??
                            SrmSettings.MonoisotopicMassCalc.GetAAModMass(unmodifiedSequence[i], i,
                                                                          unmodifiedSequence.Length);
            var avgMass = staticMod.AverageMass ??
                          SrmSettings.AverageMassCalc.GetAAModMass(unmodifiedSequence[i], i,
                                                                   unmodifiedSequence.Length);

            if (monoMass == 0 && avgMass == 0)
            {
                char aa = unmodifiedSequence[i];
                if ((staticMod.LabelAtoms & LabelAtoms.LabelsAA) != LabelAtoms.None && AminoAcid.IsAA(aa))
                {
                    string heavyFormula = SequenceMassCalc.GetHeavyFormula(aa, staticMod.LabelAtoms);
                    monoMass = SequenceMassCalc.FormulaMass(BioMassCalc.MONOISOTOPIC, heavyFormula,
                                                            SequenceMassCalc.MassPrecision);
                    avgMass = SequenceMassCalc.FormulaMass(BioMassCalc.AVERAGE, heavyFormula,
                                                           SequenceMassCalc.MassPrecision);
                }
            }
            return(new Modification(explicitMod, monoMass, avgMass));
        }
Esempio n. 3
0
 public static bool IsValidLibKey(string key)
 {
     try
     {
         SequenceMassCalc.FormulaMass(BioMassCalc.AVERAGE, key);
     }
     catch
     {
         return(false);
     }
     return(true);
 }
Esempio n. 4
0
        public void OkDialog()
        {
            var helper = new MessageBoxHelper(this);

            string name;

            if (!helper.ValidateNameTextBox(_editing ? (Control)textName : comboMod, out name))
            {
                return;
            }

            // Allow updating the original modification
            if (!_editing || !Equals(name, Modification.Name))
            {
                if (!ModNameAvailable(name))
                {
                    helper.ShowTextBoxError(_editing ? (Control)textName : comboMod,
                                            Resources.EditStaticModDlg_OkDialog_The_modification__0__already_exists, name);
                    return;
                }
            }

            string aas = comboAA.Text;

            if (string.IsNullOrEmpty(aas))
            {
                aas = null;
            }
            else
            {
                // Use the cleanest possible format.
                var sb = new StringBuilder();
                foreach (string aaPart in aas.Split(SEPARATOR_AA))
                {
                    string aa = aaPart.Trim();
                    if (aa.Length == 0)
                    {
                        continue;
                    }
                    if (sb.Length > 0)
                    {
                        sb.Append(", "); // Not L10N
                    }
                    sb.Append(aa);
                }
            }

            string      termString = comboTerm.SelectedItem.ToString();
            ModTerminus?term       = null;

            if (!string.IsNullOrEmpty(termString))
            {
                term = (ModTerminus)Enum.Parse(typeof(ModTerminus), termString);
            }

            if (cbVariableMod.Checked && aas == null && term == null)
            {
                MessageDlg.Show(this, Resources.EditStaticModDlg_OkDialog_Variable_modifications_must_specify_amino_acid_or_terminus);
                comboAA.Focus();
                return;
            }

            string     formula    = null;
            double?    monoMass   = null;
            double?    avgMass    = null;
            LabelAtoms labelAtoms = LabelAtoms.None;

            if (cbChemicalFormula.Checked)
            {
                formula = Formula;
            }
            else
            {
                labelAtoms = LabelAtoms;
            }

            // Get the losses to know whether any exist below
            IList <FragmentLoss> losses = null;

            if (listNeutralLosses.Items.Count > 0)
            {
                losses = Losses.ToArray();
            }

            if (!string.IsNullOrEmpty(formula))
            {
                try
                {
                    SequenceMassCalc.FormulaMass(BioMassCalc.MONOISOTOPIC, formula, SequenceMassCalc.MassPrecision);
                }
                catch (ArgumentException x)
                {
                    _formulaBox.ShowTextBoxErrorFormula(helper, x.Message);
                    return;
                }
            }
            else if (labelAtoms == LabelAtoms.None)
            {
                formula = null;

                // Allow formula and both masses to be empty, if losses are present
                if (NotZero(_formulaBox.MonoMass) || NotZero(_formulaBox.AverageMass) || losses == null)
                {
                    // TODO: Maximum and minimum masses should be formalized and applied everywhere
                    double mass;
                    if (!_formulaBox.ValidateMonoText(helper, -1500, 5000, out mass))
                    {
                        return;
                    }
                    monoMass = mass;
                    if (!_formulaBox.ValidateAverageText(helper, -1500, 5000, out mass))
                    {
                        return;
                    }
                    avgMass = mass;
                }
                // Loss-only modifications may not be variable
                else if (cbVariableMod.Checked)
                {
                    MessageDlg.Show(this, Resources.EditStaticModDlg_OkDialog_The_variable_checkbox_only_applies_to_precursor_modification_Product_ion_losses_are_inherently_variable);
                    cbVariableMod.Focus();
                    return;
                }
            }
            else if (aas == null && term.HasValue)
            {
                MessageDlg.Show(this, Resources.EditStaticModDlg_OkDialog_Labeled_atoms_on_terminal_modification_are_not_valid);
                return;
            }

            RelativeRT relativeRT = RelativeRT.Matching;

            if (comboRelativeRT.Visible && comboRelativeRT.SelectedItem != null)
            {
                relativeRT = RelativeRTExtension.GetEnum(comboRelativeRT.SelectedItem.ToString());
            }

            // Store state of the chemical formula checkbox for next use.
            if (cbChemicalFormula.Visible)
            {
                Settings.Default.ShowHeavyFormula = _formulaBox.FormulaVisible;
            }

            var newMod = new StaticMod(name,
                                       aas,
                                       term,
                                       cbVariableMod.Checked,
                                       formula,
                                       labelAtoms,
                                       relativeRT,
                                       monoMass,
                                       avgMass,
                                       losses);

            foreach (StaticMod mod in _existing)
            {
                if (newMod.Equivalent(mod) && !(_editing && mod.Equals(_originalModification)))
                {
                    if (DialogResult.OK == MultiButtonMsgDlg.Show(
                            this,
                            TextUtil.LineSeparate(Resources.EditStaticModDlg_OkDialog_There_is_an_existing_modification_with_the_same_settings,
                                                  string.Format("'{0}'.", mod.Name), // Not L10N
                                                  string.Empty,
                                                  Resources.EditStaticModDlg_OkDialog_Continue),
                            MultiButtonMsgDlg.BUTTON_OK))
                    {
                        Modification = newMod;
                        DialogResult = DialogResult.OK;
                    }
                    return;
                }
            }

            var uniMod = UniMod.GetModification(name, IsStructural);

            // If the modification name is not found in Unimod, check if there exists a modification in Unimod that matches
            // the dialog modification, and prompt the user to to use the Unimod modification instead.
            if (uniMod == null)
            {
                var matchingMod = UniMod.FindMatchingStaticMod(newMod, IsStructural);
                if (matchingMod != null &&
                    (ModNameAvailable(matchingMod.Name) ||
                     (_editing && Equals(matchingMod.Name, Modification.Name))))
                {
                    var result = MultiButtonMsgDlg.Show(
                        this,
                        TextUtil.LineSeparate(Resources.EditStaticModDlg_OkDialog_There_is_a_Unimod_modification_with_the_same_settings,
                                              string.Empty,
                                              string.Format(Resources.EditStaticModDlg_OkDialog_Click__Unimod__to_use_the_name___0___, matchingMod.Name),
                                              string.Format(Resources.EditStaticModDlg_OkDialog_Click__Custom__to_use_the_name___0___, name)),
                        Resources.EditStaticModDlg_OkDialog_Unimod,
                        Resources.EditStaticModDlg_OkDialog_Custom,
                        true);
                    if (result == DialogResult.Yes)
                    {
                        newMod = matchingMod.MatchVariableAndLossInclusion(newMod);   // Unimod
                    }
                    if (result == DialogResult.Cancel)
                    {
                        return;
                    }
                }
            }
            else
            {
                // If the dialog modification matches the modification of the same name in Unimod,
                // use the UnimodId.
                if (newMod.Equivalent(uniMod))
                {
                    newMod = uniMod.MatchVariableAndLossInclusion(newMod);
                }
                else
                {
                    // Finally, if the modification name is found in Unimod, but the modification in Unimod does not
                    // match the dialog modification, prompt the user to use the Unimod modification definition instead.
                    if (DialogResult.OK != MultiButtonMsgDlg.Show(
                            this,
                            TextUtil.LineSeparate(string.Format(Resources.EditStaticModDlg_OkDialog_This_modification_does_not_match_the_Unimod_specifications_for___0___, name),
                                                  string.Empty,
                                                  Resources.EditStaticModDlg_OkDialog_Use_non_standard_settings_for_this_name),
                            MultiButtonMsgDlg.BUTTON_OK))
                    {
                        return;
                    }
                }
            }

            _modification = newMod;

            DialogResult = DialogResult.OK;
        }
Esempio n. 5
0
        private MeasuredIon ValidateCustomIon(string name)
        {
            var    helper  = new MessageBoxHelper(this);
            string formula = (_formulaBox.NeutralFormula ?? string.Empty).ToString(LocalizationHelper.CurrentCulture);
            var    charge  = ValidateCharge();

            if (!charge.HasValue)
            {
                return(null);
            }
            double monoMass;
            double avgMass;

            if (!string.IsNullOrEmpty(formula))
            {
                // Mass is specified by chemical formula
                try
                {
                    monoMass = SequenceMassCalc.FormulaMass(BioMassCalc.MONOISOTOPIC, formula, SequenceMassCalc.MassPrecision);
                    avgMass  = SequenceMassCalc.FormulaMass(BioMassCalc.AVERAGE, formula, SequenceMassCalc.MassPrecision);
                }
                catch (ArgumentException x)
                {
                    helper.ShowTextBoxError(_formulaBox, x.Message);
                    return(null);
                }
            }
            else if (_formulaBox.MonoMass != null ||
                     _formulaBox.AverageMass != null)
            {
                // Mass is specified by combination of mz and charge
                formula = null;
                if (!_formulaBox.ValidateMonoText(helper))
                {
                    return(null);
                }
                if (!_formulaBox.ValidateAverageText(helper))
                {
                    return(null);
                }
                // CONSIDER(bspratt): should we switch to using adducts instead of baking ions into formula?
                _formulaBox.Adduct = Adduct.FromChargeNoMass(charge.Value); // This provokes calculation of mass from displayed mz values
                monoMass           = _formulaBox.MonoMass.Value;
                avgMass            = _formulaBox.AverageMass.Value;
            }
            else
            {
                // User hasn't fully specified either way
                _formulaBox.ShowTextBoxErrorFormula(helper,
                                                    Resources.EditMeasuredIonDlg_OkDialog_Please_specify_a_formula_or_constant_masses);
                return(null);
            }
            if (MeasuredIon.MIN_REPORTER_MASS > monoMass || MeasuredIon.MIN_REPORTER_MASS > avgMass)
            {
                _formulaBox.ShowTextBoxErrorMonoMass(helper, string.Format(Resources.EditMeasuredIonDlg_OkDialog_Reporter_ion_masses_must_be_less_than_or_equal_to__0__,
                                                                           MeasuredIon.MAX_REPORTER_MASS));
                return(null);
            }
            if (monoMass > MeasuredIon.MAX_REPORTER_MASS || avgMass > MeasuredIon.MAX_REPORTER_MASS)
            {
                _formulaBox.ShowTextBoxErrorAverageMass(helper, string.Format(Resources.EditMeasuredIonDlg_OkDialog_Reporter_ion_masses_must_be_less_than_or_equal_to__0__,
                                                                              MeasuredIon.MAX_REPORTER_MASS));
                return(null);
            }

            return(new MeasuredIon(name, formula, monoMass, avgMass, Adduct.FromChargeNoMass(charge.Value))); // Charge-only adduct: user is assumed to have placed ion elements in formula
        }
Esempio n. 6
0
        public void TestUniMod()
        {
            // UpdateTestXML is used to update the test files if the modifications in UniMod.cs
            // have changed. Before UpdateTestXML is called, TestUniMod should pass with the new changes
            // to make sure we haven't lost/broken any modifications from earlier versions of UniMod.cs.
            // Note: The test will always run against the last build XML. Run twice when updating.
            UpdateTestXML();

            foreach (StaticMod mod in UniMod.DictUniModIds.Values)
            {
                // UniModCompiler should not set the masses.
                if (mod.Formula == null)
                {
                    Assert.IsNull(mod.MonoisotopicMass);
                    Assert.IsNull(mod.AverageMass);
                }
                else
                {
                    Assert.AreEqual(mod.MonoisotopicMass,
                                    SequenceMassCalc.FormulaMass(BioMassCalc.MONOISOTOPIC, mod.Formula, SequenceMassCalc.MassPrecision));
                    Assert.AreEqual(mod.AverageMass,
                                    SequenceMassCalc.FormulaMass(BioMassCalc.AVERAGE, mod.Formula, SequenceMassCalc.MassPrecision));
                }
                // Everything amino acid/terminus that is part of the modification should be present in
                // the name of the modification.
                var aasAndTermInName = mod.Name.Split(new[] { ' ' }, 2)[1];
                if (mod.Terminus != null)
                {
                    Assert.IsTrue(aasAndTermInName.Contains(mod.Terminus.Value.ToString()));
                }
                if (mod.AAs != null)
                {
                    foreach (char aa in mod.AminoAcids)
                    {
                        Assert.IsTrue(aasAndTermInName.Contains(aa));
                    }
                }
                // Should not have label atoms if no amino acids are listed.
                if (!Equals(mod.LabelAtoms, LabelAtoms.None))
                {
                    Assert.IsTrue(mod.AAs != null);
                }
            }

            // Testing ValidateID.
            var phospho = UniMod.DictStructuralModNames["Phospho (ST)"];

            Assert.IsTrue(UniMod.ValidateID(phospho.ChangeExplicit(true)));
            Assert.IsTrue(UniMod.ValidateID(phospho.ChangeVariable(true)));
            Assert.IsFalse(UniMod.ValidateID((StaticMod)phospho.ChangeName("Phospho")));

            StreamReader staticReader = new StreamReader(GetTestStream(STATIC_LIST_FILE));
            string       staticMods   = staticReader.ReadToEnd();

            staticReader.Close();
            AssertEx.DeserializeNoError <StaticModList>(staticMods, false);

            StreamReader heavyReader = new StreamReader(GetTestStream(HEAVY_LIST_FILE));
            string       heavyMods   = heavyReader.ReadToEnd();

            heavyReader.Close();
            AssertEx.DeserializeNoError <HeavyModList>(heavyMods, false);
        }
Esempio n. 7
0
        private void UpdateAverageAndMonoTextsForFormula()
        {
            bool valid;

            try
            {
                var formula = Formula; // Get current formula and adduct

                var userinput = textFormula.Text.Trim();
                if (_editMode == EditMode.adduct_only)
                {
                    if (!string.IsNullOrEmpty(userinput) && !userinput.StartsWith(@"["))
                    {
                        // Assume they're trying to type an adduct
                        userinput = @"[" + userinput + @"]";
                    }
                    if (string.IsNullOrEmpty(NeutralFormula))
                    {
                        formula = null; // Parent molecule was described as mass only
                    }
                    else
                    {
                        formula = NeutralFormula + userinput; // Try to apply this new adduct to parent molecule
                    }
                }
                else
                {
                    formula = userinput;
                }
                string   neutralFormula;
                Molecule ion;
                Adduct   adduct;
                if (!IonInfo.IsFormulaWithAdduct(formula, out ion, out adduct, out neutralFormula))
                {
                    neutralFormula = formula;
                    if (!Adduct.TryParse(userinput, out adduct))
                    {
                        adduct = Adduct.EMPTY;
                    }
                }
                if (_editMode != EditMode.adduct_only)
                {
                    NeutralFormula = neutralFormula;
                }
                if (_editMode != EditMode.formula_only)
                {
                    Adduct = adduct;
                }
                // Update mass/mz displays
                if (string.IsNullOrEmpty(neutralFormula))
                {
                    if (!adduct.IsEmpty)
                    {
                        // No formula, but adduct changed
                        Adduct = adduct;
                        // ReSharper disable once PossibleNullReferenceException
                        GetTextFromMass(_neutralMonoMass, MassType.Monoisotopic); // Just to see if it throws or not
                        GetTextFromMass(_neutralAverageMass, MassType.Average);   // Just to see if it throws or not
                    }
                }
                else
                {
                    // Is there an isotopic label we should apply to get the mass?
                    if (IsotopeLabelsForMassCalc != null && (Adduct.IsEmpty || !Adduct.HasIsotopeLabels)) // If adduct declares an isotope, that takes precedence
                    {
                        neutralFormula = IsotopeLabelsForMassCalc.Aggregate(neutralFormula, (current, kvp) => current.Replace(kvp.Key, kvp.Value));
                    }
                    var monoMass    = SequenceMassCalc.FormulaMass(BioMassCalc.MONOISOTOPIC, neutralFormula, SequenceMassCalc.MassPrecision);
                    var averageMass = SequenceMassCalc.FormulaMass(BioMassCalc.AVERAGE, neutralFormula, SequenceMassCalc.MassPrecision);
                    GetTextFromMass(monoMass, MassType.Monoisotopic); // Just to see if it throws or not
                    GetTextFromMass(averageMass, MassType.Average);   // Just to see if it throws or not
                    MonoMass    = monoMass;
                    AverageMass = averageMass;
                }
                valid = true; // If we got here, formula parsed OK, or adduct did
                textFormula.ForeColor = Color.Black;
                if (_editMode == EditMode.adduct_only)
                {
                    textFormula.Text = userinput; // Enforce proper adduct formatting
                    if (adduct.IsEmpty)
                    {
                        valid = false; // Adduct did not parse
                    }
                }
                else if (_editMode == EditMode.formula_only)
                {
                    valid &= adduct.IsEmpty; // Should not have anything going on with adduct here
                }
            }
            catch (InvalidOperationException)
            {
                valid = false;
            }
            catch (ArgumentException)
            {
                valid = false;
            }
            if (valid)
            {
                textFormula.ForeColor = Color.Black;
            }
            else
            {
                textFormula.ForeColor = Color.Red;
                textMono.Text         = textAverage.Text = string.Empty;
            }

            // Allow direct editing of masses if direct editing of formula is allowed, but formula is empty
            MassEnabled = _editMode != EditMode.adduct_only && string.IsNullOrEmpty(_neutralFormula);
        }
Esempio n. 8
0
        public void OkDialog()
        {
            var helper = new MessageBoxHelper(this);

            string formulaLoss = _formulaBox.Formula;
            double?monoLoss    = null;
            double?avgLoss     = null;

            if (!string.IsNullOrEmpty(formulaLoss))
            {
                try
                {
                    double massMono    = SequenceMassCalc.FormulaMass(BioMassCalc.MONOISOTOPIC, formulaLoss, SequenceMassCalc.MassPrecision);
                    double massAverage = SequenceMassCalc.FormulaMass(BioMassCalc.AVERAGE, formulaLoss, SequenceMassCalc.MassPrecision);
                    if (FragmentLoss.MIN_LOSS_MASS > massMono || FragmentLoss.MIN_LOSS_MASS > massAverage)
                    {
                        _formulaBox.ShowTextBoxErrorFormula(helper, string.Format(Resources.EditFragmentLossDlg_OkDialog_Neutral_loss_masses_must_be_greater_than_or_equal_to__0__,
                                                                                  FragmentLoss.MIN_LOSS_MASS));
                        return;
                    }
                    if (massMono > FragmentLoss.MAX_LOSS_MASS || massAverage > FragmentLoss.MAX_LOSS_MASS)
                    {
                        _formulaBox.ShowTextBoxErrorFormula(helper, string.Format(Resources.EditFragmentLossDlg_OkDialog_Neutral_loss_masses_must_be_less_than_or_equal_to__0__,
                                                                                  FragmentLoss.MAX_LOSS_MASS));
                        return;
                    }
                }
                catch (ArgumentException x)
                {
                    _formulaBox.ShowTextBoxErrorFormula(helper, x.Message);
                    return;
                }
            }
            else if (_formulaBox.MonoMass != null ||
                     _formulaBox.AverageMass != null)
            {
                formulaLoss = null;
                double mass;
                if (!_formulaBox.ValidateMonoText(helper, FragmentLoss.MIN_LOSS_MASS, FragmentLoss.MAX_LOSS_MASS, out mass))
                {
                    return;
                }
                monoLoss = mass;
                if (!_formulaBox.ValidateAverageText(helper, FragmentLoss.MIN_LOSS_MASS, FragmentLoss.MAX_LOSS_MASS, out mass))
                {
                    return;
                }
                avgLoss = mass;
            }
            else
            {
                _formulaBox.ShowTextBoxErrorFormula(helper, Resources.EditFragmentLossDlg_OkDialog_Please_specify_a_formula_or_constant_masses);
                return;
            }

            // Make sure the new loss does not already exist.
            var loss = new FragmentLoss(formulaLoss, monoLoss, avgLoss, Inclusion);

            if (_existing.Contains(loss))
            {
                MessageDlg.Show(this, string.Format(Resources.EditFragmentLossDlg_OkDialog_The_loss__0__already_exists, loss));
                return;
            }

            Loss = loss;

            DialogResult = DialogResult.OK;
        }
Esempio n. 9
0
        public const string UnimodPrefix = "unimod:"; // Not L10N

        /// <summary>
        /// Constructs a ModifiedSequence from SrmSettings and PeptideDocNode.
        /// </summary>
        public static ModifiedSequence GetModifiedSequence(SrmSettings settings, PeptideDocNode docNode, IsotopeLabelType labelType)
        {
            if (docNode.Peptide.IsCustomMolecule)
            {
                return(null);
            }
            var  unmodifiedSequence          = docNode.Peptide.Sequence;
            bool includeStaticMods           = true;
            bool includeStaticHeavyMods      = false;
            List <Modification> explicitMods = new List <Modification>();

            if (null != docNode.ExplicitMods)
            {
                var staticBaseMods    = docNode.ExplicitMods.GetStaticBaseMods(labelType);
                var labelMods         = docNode.ExplicitMods.GetModifications(labelType);
                var explicitLabelType = labelType;
                if (labelMods == null && !labelType.IsLight)
                {
                    labelMods              = docNode.ExplicitMods.GetModifications(IsotopeLabelType.light);
                    explicitLabelType      = IsotopeLabelType.light;
                    includeStaticHeavyMods = true;
                }
                if (labelMods != null || staticBaseMods != null)
                {
                    IEnumerable <ExplicitMod> modsToAdd = (labelMods ?? Enumerable.Empty <ExplicitMod>())
                                                          .Concat(staticBaseMods ?? Enumerable.Empty <ExplicitMod>());
                    var monoMasses = docNode.ExplicitMods.GetModMasses(MassType.Monoisotopic, explicitLabelType);
                    var avgMasses  = docNode.ExplicitMods.GetModMasses(MassType.Average, explicitLabelType);
                    foreach (var mod in modsToAdd)
                    {
                        explicitMods.Add(new Modification(mod, monoMasses[mod.IndexAA], avgMasses[mod.IndexAA]));
                    }
                    includeStaticMods = docNode.ExplicitMods.IsVariableStaticMods && staticBaseMods == null;
                }
            }

            if (includeStaticMods || includeStaticHeavyMods)
            {
                var peptideModifications = settings.PeptideSettings.Modifications;
                for (int i = 0; i < unmodifiedSequence.Length; i++)
                {
                    IEnumerable <StaticMod> staticMods = peptideModifications.GetModifications(labelType);
                    if (!labelType.IsLight && includeStaticMods)
                    {
                        staticMods = peptideModifications.GetModifications(IsotopeLabelType.light).Concat(staticMods);
                    }
                    foreach (var staticMod in staticMods)
                    {
                        if (staticMod.IsExplicit || staticMod.IsVariable)
                        {
                            continue;
                        }
                        if (staticMod.Terminus.HasValue)
                        {
                            if (staticMod.Terminus == ModTerminus.N && i != 0)
                            {
                                continue;
                            }
                            if (staticMod.Terminus == ModTerminus.C && i != unmodifiedSequence.Length - 1)
                            {
                                continue;
                            }
                        }
                        if (!string.IsNullOrEmpty(staticMod.AAs) && !staticMod.AAs.Contains(unmodifiedSequence[i]))
                        {
                            continue;
                        }
                        var monoMass = staticMod.MonoisotopicMass ??
                                       SrmSettings.MonoisotopicMassCalc.GetAAModMass(unmodifiedSequence[i], i,
                                                                                     unmodifiedSequence.Length);
                        var avgMass = staticMod.AverageMass ??
                                      SrmSettings.AverageMassCalc.GetAAModMass(unmodifiedSequence[i], i,
                                                                               unmodifiedSequence.Length);
                        if (monoMass == 0 && avgMass == 0)
                        {
                            char aa = unmodifiedSequence[i];
                            if ((staticMod.LabelAtoms & LabelAtoms.LabelsAA) != LabelAtoms.None && AminoAcid.IsAA(aa))
                            {
                                string heavyFormula = SequenceMassCalc.GetHeavyFormula(aa, staticMod.LabelAtoms);
                                monoMass = SequenceMassCalc.FormulaMass(BioMassCalc.MONOISOTOPIC, heavyFormula,
                                                                        SequenceMassCalc.MassPrecision);
                                avgMass = SequenceMassCalc.FormulaMass(BioMassCalc.AVERAGE, heavyFormula,
                                                                       SequenceMassCalc.MassPrecision);
                            }
                        }
                        explicitMods.Add(new Modification(new ExplicitMod(i, staticMod), monoMass, avgMass));
                    }
                }
            }
            return(new ModifiedSequence(unmodifiedSequence, explicitMods, settings.TransitionSettings.Prediction.PrecursorMassType));
        }