private List<CompositionHypothesisEntry> addWater(List<CompositionHypothesisEntry> Ans)
        {
            PeriodicTable PT = new PeriodicTable();
            List<string> elementIDs = new List<string>();
            List<string> molname = new List<string>();
            for (int j = 0; j < Ans.Count(); j++)
            {
                if (Ans[j].ElementNames.Count > 0)
                {
                    for (int i = 0; i < Ans[j].ElementNames.Count(); i++)
                    {
                        elementIDs.Add(Ans[j].ElementNames[i]);
                    }
                    for (int i = 0; i < Ans[j].MoleculeNames.Count(); i++)
                    {
                        molname.Add(Ans[j].MoleculeNames[i]);
                    }
                    break;
                }
            }

            string H = "H";
            string O = "O";
            string Water = "Water";
            if (!elementIDs.Any(H.Contains))
            {
                elementIDs.Add(H);
                foreach (CompositionHypothesisEntry CH in Ans)
                {
                    CH.ElementAmount.Add(0);
                }
            }
            if (!elementIDs.Any(O.Contains))
            {
                elementIDs.Add(O);
                foreach (CompositionHypothesisEntry CH in Ans)
                {
                    CH.ElementAmount.Add(0);
                }
            }
            if (!molname.Any(Water.Contains))
            {
                molname.Add(Water);
                foreach (CompositionHypothesisEntry CH in Ans)
                {
                    CH.eqCounts.Add(0);
                }
            }
            foreach (CompositionHypothesisEntry CH in Ans)
            {

                CH.ElementAmount[elementIDs.IndexOf("H")] = CH.ElementAmount[elementIDs.IndexOf("H")] + 2;
                CH.ElementAmount[elementIDs.IndexOf("O")] = CH.ElementAmount[elementIDs.IndexOf("O")] + 1;

                CH.MassWeight = CH.MassWeight + PT.getMass("H") * 2 + PT.getMass("O");
                CH.eqCounts[molname.IndexOf("Water")] = CH.eqCounts[molname.IndexOf("Water")] + 1;
            }
            for (int i = 0; i < Ans.Count(); i++)
            {
                Ans[i].ElementNames.Clear();
                Ans[i].MoleculeNames.Clear();

                if (i == Ans.Count() - 1)
                {
                    Ans[0].ElementNames = elementIDs;
                    Ans[0].MoleculeNames = molname;
                }
            }

            return Ans;
        }
        public double AdductMassDelta()
        {
            String adduct = this.Modification[0];
            String replacement = this.Modification[1];
            //Regex for the capital letters
            string regexpattern = @"[A-Z]{1}[a-z]?[a-z]?\d?";
            MatchCollection adducts = Regex.Matches(adduct, regexpattern);
            MatchCollection replacements = Regex.Matches(replacement, regexpattern);
            //Regex for the element;
            string elementregexpattern = @"[A-Z]{1}[a-z]?[a-z]?(\(([^)]*)\))?";
            //Regex for the number of the element.
            string numberregexpattern = @"\d+";
            Double adductmass = 0;
            Double replacementmass = 0;
            PeriodicTable pTable = new PeriodicTable();
            //For each element in adducts, add up their masses.
            foreach (Match add in adducts)
            {
                String ad = Convert.ToString(add);
                String element = Convert.ToString(Regex.Match(ad, elementregexpattern));
                String snumber = Convert.ToString(Regex.Match(ad, numberregexpattern));
                Int32 number = 0;
                if (snumber == String.Empty)
                {
                    number = 1;
                }
                else
                {
                    number = Convert.ToInt32(snumber);
                }
                adductmass = adductmass + number * pTable.getMass(element);
            }
            // Adduct replacement should be the mass delta already counting the lost composition.
            ////For each element in replacements, add up their masses.
            //foreach (Match el in replacements)
            //{
            //    String element = Convert.ToString(Regex.Match(Convert.ToString(el), elementregexpattern));
            //    String snumber = Convert.ToString(Regex.Match(Convert.ToString(el), numberregexpattern));
            //    Int32 number = 0;
            //    if (snumber == String.Empty)
            //    {
            //        number = 1;
            //    }
            //    else
            //    {
            //        number = Convert.ToInt32(snumber);
            //    }
            //    replacementmass = replacementmass + number * pTable.getMass(element);
            //}

            //Finally, subtract them and obtain delta mass.
            Double dMass = adductmass - replacementmass;
            return dMass;
        }
 //This function is used by generateHypo to get the mass of a composition in the composition table.
 public Double getcompMass(GlycanCompositionTable CT, List<string> elementIDs)
 {
     Double Mass = 0;
     PeriodicTable PT = new PeriodicTable();
     for (int i = 0; i < CT.elementAmount.Count(); i++)
     {
         Mass = Mass + CT.elementAmount[i] * PT.getMass(elementIDs[i]);
     }
     return Mass;
 }
        //This class calculates delta adduct mass.
        public Double CalculateAdductMass(GlycanHypothesisCombinatorialGenerator GD)
        {
            String adduct = GD.Modification[0];
            String replacement = GD.Modification[1];
            //Regex for the capital letters
            string regexpattern = @"[A-Z]{1}[a-z]?[a-z]?\d?";
            MatchCollection adducts = Regex.Matches(adduct, regexpattern);
            MatchCollection replacements = Regex.Matches(replacement, regexpattern);
            //Regex for the element;
            string elementregexpattern = @"[A-Z]{1}[a-z]?[a-z]?(\(([^)]*)\))?";
            //Regex for the number of the element.
            string numberregexpattern = @"\d+";
            Double adductmass = 0;
            Double replacementmass = 0;
            PeriodicTable pTable = new PeriodicTable();
            //For each element in adducts, add up their masses.
            foreach (Match add in adducts)
            {
                String ad = Convert.ToString(add);
                String element = Convert.ToString(Regex.Match(ad, elementregexpattern));
                String snumber = Convert.ToString(Regex.Match(ad, numberregexpattern));
                Int32 number = 0;
                if (snumber == String.Empty)
                {
                    number = 1;
                }
                else
                {
                    number = Convert.ToInt32(snumber);
                }
                adductmass = adductmass + number * pTable.getMass(element);
            }
            //For each element in replacements, add up their masses.
            foreach (Match el in replacements)
            {
                String element = Convert.ToString(Regex.Match(Convert.ToString(el), elementregexpattern));
                String snumber = Convert.ToString(Regex.Match(Convert.ToString(el), numberregexpattern));
                Int32 number = 0;
                if (snumber == String.Empty)
                {
                    number = 1;
                }
                else
                {
                    number = Convert.ToInt32(snumber);
                }
                replacementmass = replacementmass + number * pTable.getMass(element);
            }

            //Finally, subtract them and obtain delta mass.
            Double dMass = adductmass - replacementmass;
            return dMass;
        }
 //This function is used by glycopeptide tag to populate the datagridview after adding a file.
 private void populateGPForm(String currentpath)
 {
     string extension = Path.GetExtension(currentpath);
     List<Peptide> data = new List<Peptide>();
     //This is tab delimited file.
     if (extension == ".txt")
     {
         data = ReadTabDelimitedProteinProspecter(currentpath);
     }
     //This is XML File implemented by JK
     else if (extension == ".xml")
     {
         MSDigestReport report = MSDigestReport.Load(currentpath);
         Console.WriteLine(report.Peptides.Count);
         data = report.Peptides.ConvertAll(x => new Peptide(x));
     }
     Console.WriteLine(data.Count);
     foreach (Peptide x in data)
     {
         Console.WriteLine(x);
     }
     PeriodicTable pt = new PeriodicTable();
     SequenceDisplayTextBox.Text = GetSequenceFromCleavedPeptides(data);
     foreach (Peptide pp in data)
     {
         PeptideGridView.Rows.Add(
             pp.NumGlycosylations > 0 ? 1 : 0,
             pp.Mass - (pp.Charge * pt.getMass("H+")),
             pp.Modifications,
             pp.StartAA,
             pp.EndAA,
             pp.MissedCleavages,
             pp.Sequence,
             Convert.ToString(pp.NumGlycosylations),
             pp.ProteinID
             );
     }
 }
        public CompositionHypothesisTabbedForm()
        {
            InitializeComponent();
            //Initialize the additional rules table.
            DataGridViewTextBoxColumn Formula = new DataGridViewTextBoxColumn();
            Formula.HeaderText = "Formula";
            Formula.Name = "Formula";
            Formula.ValueType = typeof(String);
            this.dataGridView3.Columns.Add(Formula);
            DataGridViewComboBoxColumn Relationship = new DataGridViewComboBoxColumn();
            Relationship.HeaderText = "Relationship";
            Relationship.Name = "Relationship";
            Relationship.Items.AddRange("=", ">", "<", "≥", "≤", "≠");
            this.dataGridView3.Columns.Add(Relationship);
            DataGridViewTextBoxColumn constraint = new DataGridViewTextBoxColumn();
            constraint.HeaderText = "constraint";
            constraint.Name = "constraint";
            constraint.ValueType = typeof(String);
            this.dataGridView3.Columns.Add(constraint);

            //Populate the tables.
            //Get the path of the source file.
            String currentpath = Application.StartupPath + "\\compositionsCurrent.cpos";
            this.populateForm(currentpath);
            PeriodicTable PT = new PeriodicTable();
            List<string> elements = PT.getElements();
            List<string> elementsInHeader = new List<string>();
            for (int j = 2; j < this.dataGridView1.ColumnCount -2; ++j)
            {
                elementsInHeader.Add(dataGridView1.Columns[j].HeaderText);
            }
            foreach (string ele in elements)
            {
                bool eleNotInTable = true;
                foreach (string element in elementsInHeader)
                {
                    if (element == ele)
                    {
                        eleNotInTable = false;
                        comboBox2.Items.Add(ele);
                    }
                }
                if (eleNotInTable)
                    comboBox1.Items.Add(ele);
            }
            try
            {
                dataGridView1.AllowUserToAddRows = false;
                dataGridView1.Columns[0].ReadOnly = true;
                dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
                dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
                dataGridView3.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            }
            catch (Exception compoex)
            {
                MessageBox.Show("Error in populating GlycanCompositions Table. Error:" + compoex);
            }
        }
        private void BuildGlycopeptideHypothesis1(string comhypopath)
        {
            List<CompositionHypothesisEntry> CHy = getCompHypo(comhypopath);
            List<string> elementIDs = new List<string>();
            List<string> molename = new List<string>();
            for (int j = 0; j < CHy.Count(); j++)
            {
                if (CHy[j].ElementNames.Count > 0)
                {
                    for (int i = 0; i < CHy[j].ElementNames.Count(); i++)
                    {
                        elementIDs.Add(CHy[j].ElementNames[i]);
                    }
                    for (int i = 0; i < CHy[j].MoleculeNames.Count(); i++)
                    {
                        molename.Add(CHy[j].MoleculeNames[i]);
                    }
                    break;
                }
            }

            String AddRep = CHy[0].AddRep;

            int indexH = 0;
            int indexO = 0;
            int indexWater = 0;
            try
            {
                indexH = elementIDs.IndexOf("H");
                indexO = elementIDs.IndexOf("O");
                indexWater = molename.IndexOf("Water");
                if (indexWater < 0)
                {
                    indexWater = molename.IndexOf("G:Water");
                }
                if (indexWater < 0)
                {
                    throw new Exception("No Water!");
                }
            }
            catch
            {
                MessageBox.Show("Your composition hypothesis contains a compound without Water. Job terminated.");
                return;
            }

            List<Peptide> PP = GetPeptidesFromTable();
            List<CompositionHypothesisEntry> Ans = new List<CompositionHypothesisEntry>();
            //Ans.AddRange(CHy);
            PeriodicTable PT = new PeriodicTable();
            for (int i = 0; i < PP.Count; i++)
            {
                if (PP[i].Selected)
                {
                    Int32 Count = Convert.ToInt32(PP[i].NumGlycosylations);
                    List<CompositionHypothesisEntry> Temp = new List<CompositionHypothesisEntry>();
                    CompositionHypothesisEntry temp = new CompositionHypothesisEntry();
                    //First line:
                    temp.CompoundComposition = "";
                    temp.AdductNum = 0;
                    temp.AddRep = "";
                    temp.MassWeight = PP[i].Mass;
                    for (int s = 0; s < CHy[0].eqCounts.Count; s++)
                    {
                        temp.eqCounts.Add(0);
                    }
                    for (int s = 0; s < CHy[0].ElementAmount.Count; s++)
                    {
                        temp.ElementAmount.Add(0);
                    }
                    //columns for glycopeptides
                    temp.PepModification = PP[i].Modifications;
                    temp.PepSequence = PP[i].Sequence;
                    temp.MissedCleavages = PP[i].MissedCleavages;
                    temp.StartAA = PP[i].StartAA;
                    temp.EndAA = PP[i].EndAA;
                    temp.NumGlycosylations = 0;
                    Temp.Add(temp);
                    for (int j = 0; j < Count; j++)
                    {
                        List<CompositionHypothesisEntry> Temp2 = new List<CompositionHypothesisEntry>();
                        for (int k = 0; k < Temp.Count(); k++)
                        {
                            //need to reread the file and get new reference, because c# keeps passing by reference which creates a problem.
                            List<CompositionHypothesisEntry> CH = getCompHypo(comhypopath);
                            for (int l = 0; l < CH.Count(); l++)
                            {
                                CompositionHypothesisEntry temp2 = new CompositionHypothesisEntry();
                                temp2 = CH[l];
                                temp2.NumGlycosylations = Temp[k].NumGlycosylations + 1;
                                temp2.PepModification = Temp[k].PepModification;
                                temp2.PepSequence = Temp[k].PepSequence;
                                temp2.MissedCleavages = Temp[k].MissedCleavages;
                                temp2.StartAA = Temp[k].StartAA;
                                temp2.EndAA = Temp[k].EndAA;
                                List<string> forsorting = new List<string>();
                                forsorting.Add(Temp[k].CompoundComposition);
                                forsorting.Add(temp2.CompoundComposition);
                                forsorting = forsorting.OrderBy(a => a).ToList();
                                temp2.CompoundComposition = forsorting[0] + forsorting[1];
                                temp2.AdductNum = temp2.AdductNum + Temp[k].AdductNum;
                                for (int s = 0; s < temp2.eqCounts.Count; s++)
                                {
                                    temp2.eqCounts[s] = temp2.eqCounts[s] + Temp[k].eqCounts[s];
                                }
                                for (int s = 0; s < temp2.ElementAmount.Count; s++)
                                {
                                    temp2.ElementAmount[s] = temp2.ElementAmount[s] + Temp[k].ElementAmount[s];
                                }
                                for (int ui = 0; ui < molename.Count(); ui++)
                                {
                                    if (molename[ui] == "Water")
                                    {
                                        if (temp2.eqCounts[ui] > 0)
                                        {
                                            temp2.eqCounts[ui] = temp2.eqCounts[ui] - 1;
                                        }
                                        break;
                                    }
                                }
                                #region Modified by JK
                                //temp2.elementAmount[indexH] = temp2.elementAmount[indexH] - 2;
                                //temp2.elementAmount[indexO] = temp2.elementAmount[indexO] - 1;
                                //if (temp2.elementAmount[indexO] < 0)
                                //    temp2.elementAmount[indexO] = 0;
                                //if (temp2.elementAmount[indexH] < 0)
                                //    temp2.elementAmount[indexH] = 0;

                                /* These fields are not present in the Database-generated hypothesis,
                                 * but they are not appropriately error-checked when computed earlier.
                                 * This bandaid should let existing files work while letting Database-
                                 * generated ones through as well. This function is very difficult to
                                 * trace in and would benefit from rewriting in the future.
                                 */
                                if ((indexH > 0) && (indexO > 0))
                                {
                                    temp2.ElementAmount[indexH] = temp2.ElementAmount[indexH] - 2;
                                    temp2.ElementAmount[indexO] = temp2.ElementAmount[indexO] - 1;
                                    if (temp2.ElementAmount[indexO] < 0)
                                        temp2.ElementAmount[indexO] = 0;
                                    if (temp2.ElementAmount[indexH] < 0)
                                        temp2.ElementAmount[indexH] = 0;
                                }
                                //else
                                //{
                                //    temp2.elementAmount[indexH] = 0;
                                //    temp2.elementAmount[indexO] = 0;
                                //}
                                #endregion
                                //Hard coded removal of extra water from neutral Charge glycan.
                                temp2.MassWeight = temp2.MassWeight + Temp[k].MassWeight - PT.getMass("H") * 2 - PT.getMass("O");
                                Temp2.Add(temp2);
                            }
                        }
                        Temp.AddRange(Temp2);
                    }
                    Ans.AddRange(Temp);
                }
            }
            //Remove Duplicates from CHy
            Ans = Ans.OrderBy(a => a.MassWeight).ToList();
            CHy.Clear();
            for (int i = 0; i < Ans.Count() - 1; i++)
            {
                bool thesame = false;
                bool equal = (Ans[i].eqCounts.Count == Ans[i + 1].eqCounts.Count) && new HashSet<int>(Ans[i].eqCounts).SetEquals(Ans[i + 1].eqCounts);
                if (Ans[i].PepSequence == Ans[i + 1].PepSequence && equal)
                {
                    if (Ans[i].AdductNum == Ans[i + 1].AdductNum && Ans[i].PepModification == Ans[i + 1].PepModification)
                    {
                        thesame = true;
                    }
                }
                if (!thesame)
                    CHy.Add(Ans[i]);
            }
            Console.WriteLine("Ans Length {0}", Ans.Count());
            //Enter elementID and MoleNames into each rows
            CHy.Add(Ans[Ans.Count() - 1]);
            for (int i = 0; i < CHy.Count(); i++)
            {
                CHy[i].ElementNames.Clear();
                CHy[i].MoleculeNames.Clear();

                if (i == CHy.Count() - 1)
                {
                    CHy[0].ElementNames = elementIDs;
                    CHy[0].MoleculeNames = molename;
                }
            }

            //Obtain the Name of the adduct molecules:
            GlycanHypothesisCombinatorialGenerator GD = new GlycanHypothesisCombinatorialGenerator();
            GD.Modification = AddRep.Split('/');

            //Send to generate DataTable
            Console.WriteLine(CHy[0]);
            theComhypoOnTab2 = genDT(CHy, GD);
        }
        //This class calculates delta adduct mass.
        private Double adductMass(List<CompositionHypothesisEntry> comhyp)
        {
            String adduct = "";
            String replacement = "";
            try
            {
                String AddRep = comhyp[1].AddRep;
                String[] AddandRep = AddRep.Split('/');
                adduct = AddandRep[0];
                replacement = AddandRep[1];
            }
            catch
            {
                adduct = "0";
                replacement = "0";
            }

            //Regex for the capital letters
            string regexpattern = @"[A-Z]{1}[a-z]?[a-z]?\d?";
            MatchCollection adducts = Regex.Matches(adduct, regexpattern);
            MatchCollection replacements = Regex.Matches(replacement, regexpattern);
            //Regex for the element;
            string elementregexpattern = "[A-Z]{1}[a-z]?[a-z]?";
            //Regex for the number of the element.
            string numberregexpattern = "[0-9]*$";
            Double adductmass = 0;
            Double replacementmass = 0;
            PeriodicTable pTable = new PeriodicTable();
            //Console.WriteLine("Adduct String {0}, {1} Adduct Matches {1}", adduct, adducts);
            //For each element in adducts, add up their masses.
            foreach (Match add in adducts)
            {
                String ad = Convert.ToString(add);
                String element = Convert.ToString(Regex.Match(ad, elementregexpattern));
                String snumber = Convert.ToString(Regex.Match(ad, numberregexpattern));
                Int32 number = 0;
                if (snumber == String.Empty)
                {
                    number = 1;
                }
                else
                {
                    number = Convert.ToInt32(snumber);
                }

                adductmass = adductmass + number * pTable.getMass(element);
            }
            //For each element in replacements, add up their masses.
            //Console.WriteLine("Replacement String {0}, {1} Replacement Matches {1}", replacement, replacements);
            foreach (Match rep in replacements)
            {
                String el = Convert.ToString(rep);
                String element = Convert.ToString(Regex.Match(el, elementregexpattern));
                String snumber = Convert.ToString(Regex.Match(el, numberregexpattern));
                Int32 number = 0;
                if (snumber == String.Empty)
                {
                    number = 1;
                }
                else
                {
                    number = Convert.ToInt32(Regex.Match(el, numberregexpattern));
                }
                replacementmass = replacementmass + number * pTable.getMass(element);
            }

            //Finally, subtract them and obtain delta mass.
            Double dMass = adductmass - replacementmass;
            return dMass;
        }