/// <summary>
        /// Read table from http://users.rcn.com/jkimball.ma.ultranet/BiologyPages/C/Codons.html
        /// </summary>
        private void ReadTheGeneticCode()
        {
            Debug.Assert(CodonToAminoAcid == null);             // real assert
            CodonToAminoAcid    = new Dictionary <string, GeneticCodeMapping>();
            AminoAcidCollection = new Dictionary <string, bool>();

            //!!!could load these into memory instead of reading them over and over again
            string sTheGenenicCodeFile = @"GeneticCodeDna.txt";             //!!!const

            using (StreamReader streamreaderTheGenenicCodeFile = OpenResource(sTheGenenicCodeFile))
            {
                string sLine = null;
                while (null != (sLine = streamreaderTheGenenicCodeFile.ReadLine()))
                {
                    string[] rgFields = sLine.Split('\t');
                    SpecialFunctions.CheckCondition(rgFields.Length == 3);            //!!!raise error
                    string sCodon = rgFields[0];
                    SpecialFunctions.CheckCondition(sCodon.Length == 3);              //!!!raise error
                    string             sAminoAcid          = rgFields[1];
                    bool               bNormal             = bool.Parse(rgFields[2]); //!!!could raise error
                    GeneticCodeMapping aGeneticCodeMapping = new GeneticCodeMapping(sCodon, sAminoAcid, bNormal);
                    CodonToAminoAcid.Add(sCodon, aGeneticCodeMapping);

                    if (!AminoAcidCollection.ContainsKey(sAminoAcid))
                    {
                        AminoAcidCollection.Add(sAminoAcid, true);
                    }
                }
            }
        }
        public string GenticCode(string codon, out bool bAcidOrStop)
        {
            SpecialFunctions.CheckCondition(codon.Length == 3);             //!!!raise error

            //If unambiguous, look it up and return it
            if (CodonToAminoAcid.ContainsKey(codon))
            {
                GeneticCodeMapping aGeneticCodeMapping = (GeneticCodeMapping)CodonToAminoAcid[codon];
                string             sAminoAcid          = aGeneticCodeMapping.AminoAcid;
                bAcidOrStop = true;
                return(sAminoAcid);
            }

            //If ambiguous, try every possiblity for this 1st ambiguity and see if the results are the same (this is recursive)
            for (int i = 0; i < codon.Length; ++i)
            {
                char c = codon[i];
                if (Ambiguous1LetterNucCodeToChoices.ContainsKey(c))
                {
                    string sAminoAcidAll = null;
                    bAcidOrStop = false;
                    foreach (char cNucleotide in (string)Ambiguous1LetterNucCodeToChoices[c])
                    {
                        string sNewCodon = string.Format("{0}{1}{2}", codon.Substring(0, i), cNucleotide, codon.Substring(i + 1));
                        Debug.Assert(sNewCodon.Length == 3);                      //real assert
                        Debug.Assert(sNewCodon != codon);                         // real assert
                        string sAminoAcid = GenticCode(sNewCodon, out bAcidOrStop);
                        if (!bAcidOrStop)
                        {
                            goto CantFixAmbiguity;
                        }
                        if (sAminoAcidAll == null)
                        {
                            sAminoAcidAll = sAminoAcid;
                        }
                        else
                        {
                            if (sAminoAcidAll != sAminoAcid)
                            {
                                //goto CantFixAmbiguity;
                                sAminoAcidAll = "Ambiguous Amino Acid";                                 //!!!const
                            }
                        }
                    }
                    Debug.Assert(sAminoAcidAll != null);                     //!!!???
                    return(sAminoAcidAll);
                }
            }

CantFixAmbiguity:

            bAcidOrStop = false;
            return("Not an amino acid: '" + codon + "'");
        }
        public void GenticCode(string codon, ref SimpleAminoAcidSet aminoAcidCollection)
        {
            SpecialFunctions.CheckCondition(codon.Length == 3);    //!!!raise error
            Debug.Assert(aminoAcidCollection != null);             //real assert

            //If unambiguous, look it up and return it
            if (CodonToAminoAcid.ContainsKey(codon))
            {
                GeneticCodeMapping aGeneticCodeMapping = (GeneticCodeMapping)CodonToAminoAcid[codon];
                string             sAminoAcid          = aGeneticCodeMapping.AminoAcid;
                aminoAcidCollection.AddOrCheck(sAminoAcid);
                return;
            }

            //If ambiguous, try every possiblity for this 1st ambiguity and see if the results are the same (this is recursive)

            int  iFirstAmbiguity = 0;
            char c = char.MinValue;

            for (; iFirstAmbiguity < codon.Length; ++iFirstAmbiguity)
            {
                c = codon[iFirstAmbiguity];
                if (Ambiguous1LetterNucCodeToChoices.ContainsKey(c))
                {
                    break;
                }
                SpecialFunctions.CheckCondition("ATCG".Contains(c.ToString()), string.Format("Illegal nucleotide of '{0}'", c));
            }
            SpecialFunctions.CheckCondition(iFirstAmbiguity < codon.Length);             //!!!raise error - Is CodonToAminoAcid table missing a value?

            foreach (char cNucleotide in (string)Ambiguous1LetterNucCodeToChoices[c])
            {
                string sNewCodon = string.Format("{0}{1}{2}", codon.Substring(0, iFirstAmbiguity), cNucleotide, codon.Substring(iFirstAmbiguity + 1));
                Debug.Assert(sNewCodon.Length == 3);              //real assert
                Debug.Assert(sNewCodon != codon);                 // real assert
                GenticCode(sNewCodon, ref aminoAcidCollection);
            }
        }