/// <summary> /// Tests whether either N fused to C or C fused to N has a valid combination. If both are being tested, the function /// returns whether either has a valid combination /// </summary> /// <param name="multiplicity"></param> /// <param name="cn"></param> /// <param name="other"></param> /// <param name="alignment"></param> /// <param name="ntermCnTest"></param> /// <param name="ctermCnTest"></param> /// <param name="minSubstructureLength"></param> /// <returns></returns> public static bool TestClashCn(int multiplicity, IStructure cn, IStructure other, TransformSequenceAlignment alignment, bool ntermCnTest = true, bool ctermCnTest = true, int minSubstructureLength = 0) { Trace.Assert(minSubstructureLength >= 0); IChain cnChain = cn[alignment.ChainIndex1]; IChain otherChain = other[alignment.ChainIndex2]; if (ntermCnTest) { int finalOtherIndex = Math.Min(otherChain.Count - 1, alignment.Range2.End + minSubstructureLength - 1); Trace.Assert(alignment.Range1.Start < cnChain.Count); Trace.Assert(0 <= alignment.Range2.End && alignment.Range2.End < otherChain.Count && finalOtherIndex < otherChain.Count); IChain copyCn = new Chain(cnChain[0, alignment.Range1.Start]); IChain copyOther = new Chain(otherChain[alignment.Range2.End, finalOtherIndex], true); copyOther.Transform(alignment.Align2); if (!Clash.AnyContact(copyCn, copyOther, Clash.ContactType.MainchainMainchainClash)) { copyCn.AddRange(copyOther); AxisPattern <IChain> pattern = new AxisPattern <IChain>(Vector3.UnitZ, multiplicity, copyCn); IChain[] neighbors = pattern[1, multiplicity - 1].ToArray(); //IChain[] pattern = CxUtilities.Pattern(copyCn, Vector3.UnitZ, multiplicity, new int[] { 0 }, true); if (!Clash.AnyContact(new IChain[] { copyCn }, neighbors, Clash.ContactType.MainchainMainchainClash)) { return(false); } } } if (ctermCnTest) { int firstOtherIndex = Math.Max(0, alignment.Range2.Start - minSubstructureLength + 1); Trace.Assert(0 <= alignment.Range1.End && alignment.Range1.End < cnChain.Count); Trace.Assert(0 <= firstOtherIndex && firstOtherIndex < otherChain.Count && alignment.Range2.Start < otherChain.Count); IChain copyCn = new Chain(cnChain[alignment.Range1.End, cnChain.Count - 1]); IChain copyOther = new Chain(otherChain[firstOtherIndex, alignment.Range2.Start], true); copyOther.Transform(alignment.Align2); if (!Clash.AnyContact(copyCn, copyOther, Clash.ContactType.MainchainMainchainClash)) { copyCn.AddRange(copyOther); AxisPattern <IChain> pattern = new AxisPattern <IChain>(Vector3.UnitZ, multiplicity, copyCn); IChain[] neighbors = pattern[1, multiplicity - 1].ToArray(); //IChain[] pattern = CxUtilities.Pattern(copyCn, Vector3.UnitZ, multiplicity, new int[] { 0 }, true); if (!Clash.AnyContact(new IChain[] { copyCn }, neighbors, Clash.ContactType.MainchainMainchainClash)) { return(false); } } } return(true); }
public static IChain GetChain(IChain[] peptides, SequenceAlignment[] alignments, Selection immutableAas) { IChain fusion = new Chain(); // Do all pairwise analysis for (int i = 0; i < peptides.Length - 1; i++) { // Determine the ranges outside of the splice int start1 = i == 0 ? 0 : alignments[i - 1].Range2.End + 1; int end1 = alignments[i].Range1.Start - 1; int start2 = alignments[i].Range2.End + 1; int end2 = i < alignments.Length - 1 ? alignments[i + 1].Range1.Start - 1 : peptides[i + 1].Count - 1; // Add the non-overlapping region of the first peptide if (start1 <= end1) { foreach (Aa aa in peptides[i][start1, end1]) { Aa copy = new Aa(aa, i == 0 && start1 == 0, false); copy.NodeTransform = aa.TotalTransform; fusion.Add(copy); } } // Add the alignment region, selecting either from the first or second peptide so as to minimize clashes with the sidechains that // are for sure being kept on either side SequenceAlignment alignment = alignments[i]; Debug.Assert(alignment.Range1.Length == alignment.Range2.Length); for (int alignmentOffset = 0; alignmentOffset < alignment.Range1.Length; alignmentOffset++) { int index1 = alignment.Range1.Start + alignmentOffset; int index2 = alignment.Range2.Start + alignmentOffset; IAa option1 = peptides[i][index1]; IAa option2 = peptides[i + 1][index2]; bool nTerminus = i == 0 && index1 == 0; bool cTerminus = (i == peptides.Length - 2) && (index2 == peptides[i + 1].Count - 1); if (immutableAas.Aas.Contains(option1)) { Aa copy = new Aa(option1, nTerminus, cTerminus); copy.NodeTransform = option1.TotalTransform; fusion.Add(copy); } else if (immutableAas.Aas.Contains(option2)) { Aa copy = new Aa(option2, nTerminus, cTerminus); copy.NodeTransform = option2.TotalTransform; fusion.Add(copy); } else { if (option2.Letter == 'P' && index1 >= 4) { SS[] ss1 = SecondaryStructure.GetPhiPsiSS(peptides[i], 5); bool allHelical = (ss1[index1] | ss1[index1 - 1] | ss1[index1 - 2] | ss1[index1 - 3] | ss1[index1 - 4]) == SS.Helix; if (allHelical) { Aa copy = new Aa(option1, nTerminus, cTerminus); copy.NodeTransform = option1.TotalTransform; fusion.Add(copy); continue; } } // Otherwise, select the residue with fewer clashes int clashCount1 = end2 >= start2? peptides[i + 1][start2, end2].Select(other => Clash.AnyContact(other, option1, Clash.ContactType.SidechainSidechainClash) ? 1 : 0).Aggregate(0, (a, b) => a + b) : 0; int clashCount2 = end1 >= start1? peptides[i][start1, end1].Select(other => Clash.AnyContact(other, option2, Clash.ContactType.SidechainSidechainClash) ? 1 : 0).Aggregate(0, (a, b) => a + b) : 0; if (clashCount1 <= clashCount2) { Aa copy = new Aa(option1, nTerminus, cTerminus); copy.NodeTransform = option1.TotalTransform; fusion.Add(copy); continue; } if (clashCount2 < clashCount1) { Aa copy = new Aa(option2, nTerminus, cTerminus); copy.NodeTransform = option2.TotalTransform; fusion.Add(copy); continue; } } } // Add the non-overlapping region of the last peptide if (i == peptides.Length - 2 && start2 <= end2) { foreach (Aa aa in peptides[i + 1][start2, end2]) { Aa copy = new Aa(aa, false, aa.IsCTerminus); copy.NodeTransform = aa.TotalTransform; fusion.Add(copy); } } } return(fusion); }