public static Tuple <string, string, int, string>[] FromResnResi // (operation, wt_resn, wt_resi, mut_resn)[] (Tuple <string, int>[] wt_resn_resi , Tuple <string, int>[] mut_resn_resi , Tuple <int, int> rngLcsLen ) { var lcs = HSequence.LongCommSubseq.GetLongCommSubseq(wt_resn_resi, mut_resn_resi); if (rngLcsLen != null) { if ((lcs.lcs_resn.Length < rngLcsLen.Item1) || (rngLcsLen.Item2 < lcs.lcs_resn.Length)) { return(null); } } List <Tuple <string, string, int, string> > mutationinfos = new List <Tuple <string, string, int, string> >(); // (operation, wt_resn, wt_resi, mut_resn) //var aminoacids = HBioinfo.AminoAcids.ToDictionaryBy3Letter(true); //string[] mutate = new string[0]; for (int i = 0; i < lcs.lcs_oper1to2.Length; i++) { if (lcs.lcs_oper1to2[i].Item1 == LCS.Oper.Match) { continue; } /// 1. collecting deletes and inserts until next match List <int> idxs_del = new List <int>(); List <int> idxs_ins = new List <int>(); int last_j = i; for (int j = i; j < lcs.lcs_oper1to2.Length; j++) { if (lcs.lcs_oper1to2[j].Item1 == LCS.Oper.Match) { break; } if (lcs.lcs_oper1to2[j].Item1 == LCS.Oper.Delete) { idxs_del.Add(j); } if (lcs.lcs_oper1to2[j].Item1 == LCS.Oper.Insert) { idxs_ins.Add(j); } last_j = j; } /// 2. determine matching del-ins List <Tuple <int, int> > idxs_del_ins = new List <Tuple <int, int> >(); while ((idxs_del.Count != 0) && (idxs_ins.Count != 0)) { int idx_del = (i == 0) ? idxs_del.Last() : idxs_del.First(); int idx_ins = idxs_ins.First(); idxs_del_ins.Add(new Tuple <int, int>(idx_del, idx_ins)); HDebug.Verify(idxs_del.Remove(idx_del)); HDebug.Verify(idxs_ins.Remove(idx_ins)); } /// 3. handle mutation informations while ((idxs_del.Count != 0) || (idxs_ins.Count != 0) || (idxs_del_ins.Count != 0)) { Tuple <int, int> idx_del_ins = null; int idx_del = int.MaxValue; if (idxs_del.Count > 0) { idx_del = idxs_del.First(); } int idx_ins = int.MaxValue; if (idxs_ins.Count > 0) { idx_ins = idxs_ins.First(); } int idx_rep = int.MaxValue; if (idxs_del_ins.Count > 0) { idx_del_ins = idxs_del_ins.First(); idx_rep = idx_del_ins.HToArray().Min(); } int min_idx = HMath.HMin(idx_del, idx_ins, idx_rep); HDebug.Assert(min_idx != int.MaxValue); if (idx_del == min_idx) { string resn1 = lcs.lcs_oper1to2[idx_del].Item2; int resi1 = lcs.lcs_oper1to2[idx_del].Item3.Value; //string mutatei = string.Format("delete {0}{1}", aminoacids[resn].name1, resi); //mutate = mutate.HAdd(mutatei); mutationinfos.Add(new Tuple <string, string, int, string>("delete", resn1, resi1, null)); HDebug.Verify(idxs_del.Remove(idx_del)); continue; } if (idx_ins == min_idx) { string resn_insertafter = (i == 0) ? " " : lcs.lcs_oper1to2[i - 1].Item2; int resi_insertafter = (i == 0) ? int.MinValue : lcs.lcs_oper1to2[i - 1].Item3.Value; string resn2 = lcs.lcs_oper1to2[idx_ins].Item2; HDebug.Assert(lcs.lcs_oper1to2[idx_ins].Item3 == null); mutationinfos.Add(new Tuple <string, string, int, string>("insert", resn_insertafter, resi_insertafter, resn2)); HDebug.Verify(idxs_ins.Remove(idx_ins)); continue; } if (idx_rep == min_idx) { int idel = idx_del_ins.Item1; int iins = idx_del_ins.Item2; string resn1 = lcs.lcs_oper1to2[idel].Item2; int resi1 = lcs.lcs_oper1to2[idel].Item3.Value; string resn2 = lcs.lcs_oper1to2[iins].Item2; HDebug.Assert(lcs.lcs_oper1to2[iins].Item3 == null); //string mutatei = string.Format("{0}{1}{2}", aminoacids[resn1].name1, resi1, aminoacids[resn2].name1); //mutate = mutate.HAdd(mutatei); mutationinfos.Add(new Tuple <string, string, int, string>("replace", resn1, resi1, resn2)); HDebug.Verify(idxs_del_ins.Remove(idx_del_ins)); continue; } } i = last_j; continue; } return(mutationinfos.ToArray()); }