/// <summary>
        /// This method returns a list of amino acid codes that match any of the specified true properties.  If all parameter properties are false, it returns a list of
        /// </summary>
        /// <param name="aminoAcidData"></param>
        /// <param name="aminoAcidPropertyMatchType"></param>
        /// <param name="matchValue"></param>
        /// <returns></returns>
        public static string ListAminoAcidsByProperty(AminoAcidProperties <bool> aminoAcidData, AminoAcidPropertyMatchType aminoAcidPropertyMatchType = AminoAcidPropertyMatchType.AnyTrueMatch, double matchValue = 0)
        {
            var result = new List <string>();

            var aminoAcidDataPropertiesArray = aminoAcidData.PropertiesArray();

            for (var index = 0; index < AminoAcidTotals.TotalAminoAcids(); index++)
            {
                var aa = AminoAcidConversions.AminoAcidNumberToAminoAcidObject(index + 1);
                //aminoAcidDataPropertiesArray = aa.PropertiesArray();

                var propertyMatches = new AminoAcidProperties <bool>()
                {
                    //Acidic =      aminoAcidData.Acidic        == aa.Acidic,
                    Aliphatic   = aminoAcidData.Aliphatic == aa.Aliphatic,
                    Aromatic    = aminoAcidData.Aromatic == aa.Aromatic,
                    Charged     = aminoAcidData.Charged == aa.Charged,
                    Hydrophobic = aminoAcidData.Hydrophobic == aa.Hydrophobic,
                    Hydroxylic  = aminoAcidData.Hydroxylic == aa.Hydroxylic,
                    Negative    = aminoAcidData.Negative == aa.Negative,
                    Polar       = aminoAcidData.Polar == aa.Polar,
                    Positive    = aminoAcidData.Positive == aa.Positive,
                    Small       = aminoAcidData.Small == aa.Small,
                    Sulphur     = aminoAcidData.Sulphur == aa.Sulphur,
                    Tiny        = aminoAcidData.Tiny == aa.Tiny,
                };

                var matchedPropertiesArray = propertyMatches.PropertiesArray();

                // number of equal boolean values in aminoAcidData and aa
                var totalMatchingProperties = matchedPropertiesArray.Where(a => a).Count();

                var totalTrueMatchingProperties  = aminoAcidDataPropertiesArray.Where((a, i) => a && matchedPropertiesArray[i]).Count();
                var totalFalseMatchingProperties = aminoAcidDataPropertiesArray.Where((a, i) => !a && matchedPropertiesArray[i]).Count();

                var totalTrueParameterProperties  = aminoAcidDataPropertiesArray.Count(a => a);
                var totalFalseParameterProperties = aminoAcidDataPropertiesArray.Count(a => !a);

                var percentageMatchingProperties      = totalMatchingProperties / matchedPropertiesArray.Length;
                var percentageTrueMatchingProperties  = totalTrueParameterProperties > 0 ? totalTrueMatchingProperties / totalTrueParameterProperties : 0;
                var percentageFalseMatchingProperties = totalFalseParameterProperties > 0 ? totalFalseMatchingProperties / totalFalseParameterProperties : 0;

                var noPropertyMatches  = totalMatchingProperties == 0;
                var anyPropertyMatches = totalMatchingProperties > 0;
                var allPropertiesMatch = matchedPropertiesArray.Length == totalMatchingProperties;

                var anyTrueMatch  = aminoAcidDataPropertiesArray.Where((a, i) => a && matchedPropertiesArray[i]).Any();
                var anyFalseMatch = aminoAcidDataPropertiesArray.Where((a, i) => !a && matchedPropertiesArray[i]).Any();

                var allTrueMatch  = aminoAcidDataPropertiesArray.Where((a, i) => a && matchedPropertiesArray[i]).Count() == aminoAcidDataPropertiesArray.Length;
                var allFalseMatch = aminoAcidDataPropertiesArray.Where((a, i) => !a && matchedPropertiesArray[i]).Count() == aminoAcidDataPropertiesArray.Length;

                if ((aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.AllMatch && allPropertiesMatch) ||
                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.AllTrueMatch && allTrueMatch) ||
                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.AllFalseMatch && allFalseMatch) ||

                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.AnyMatch && anyPropertyMatches) ||
                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.AnyTrueMatch && anyTrueMatch) ||
                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.AnyFalseMatch && anyFalseMatch) ||

                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.NoneMatch && noPropertyMatches) ||

                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.MininumMatch && totalMatchingProperties >= matchValue) ||
                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.MininumTrueMatch && totalTrueMatchingProperties >= matchValue) ||
                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.MininumFalseMatch && totalFalseMatchingProperties >= matchValue) ||

                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.PercentageMatch && percentageMatchingProperties >= matchValue) ||
                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.PercentageTrueMatch && percentageTrueMatchingProperties >= matchValue) ||
                    (aminoAcidPropertyMatchType == AminoAcidPropertyMatchType.PercentageFalseMatch && percentageFalseMatchingProperties >= matchValue))
                {
                    result.Add(aa.Code1L);
                }
            }

            var resultStr = string.Join("", result.OrderBy(a => a).ToArray());

            return(resultStr);
        }
        public static string FindProteinInterfaceAminoAcidCommonPropertiesMotif(List <string> proteinInterfaceSequenceList, AminoAcidPropertyMatchType aminoAcidPropertyMatchType, double matchValue = 0)
        {
            if (proteinInterfaceSequenceList == null)
            {
                throw new ArgumentNullException(nameof(proteinInterfaceSequenceList));
            }

            var totalProteinInterfaces = proteinInterfaceSequenceList.Count;

            var proteinInterfaceLength = proteinInterfaceSequenceList.Select(a => a.Length).Max();

            var aminoAcidObjects = new AminoAcidProperties <bool> [TotalAminoAcids];

            for (var aaIndex = 0; aaIndex < aminoAcidObjects.Length; aaIndex++)
            {
                aminoAcidObjects[aaIndex] = AminoAcidConversions.AminoAcidNumberToAminoAcidObject(aaIndex + 1);
            }

            var aminoAcidPositionCount = new AminoAcidProperties <int> [proteinInterfaceLength];

            for (var position = 0; position < aminoAcidPositionCount.Length; position++)
            {
                aminoAcidPositionCount[position] = new AminoAcidProperties <int>();
            }

            var motifs = new List <string>();

            for (int positionIndex = 0; positionIndex < proteinInterfaceLength; positionIndex++)
            {
                string positionMotif = "";

                foreach (var aaCode in proteinInterfaceSequenceList.Where(a => a.Length > positionIndex).Select(a => a[positionIndex]).Distinct().ToArray())
                {
                    if (!char.IsLetterOrDigit(aaCode) || NonStandardAminoAcids.Contains(aaCode))
                    {
                        continue;
                    }

                    var aminoAcid = aminoAcidObjects[AminoAcidConversions.AminoAcidNameToNumber(aaCode) - 1];

                    var matches = AminoAcidConversions.ListAminoAcidsByProperty(aminoAcid, aminoAcidPropertyMatchType, matchValue);

                    positionMotif += string.Join("", matches.Where(a => !positionMotif.Contains(a) && !NonStandardAminoAcids.Contains(a)).ToArray());
                }

                motifs.Add(positionMotif);
            }

            return(MotifFormatter(motifs));
        }