/// <summary> /// Find the previous eligible sequence for alignment/extension /// </summary> /// <param name="alignments">List of alignment</param> /// <param name="currentAlignment">Current alignment</param> /// <returns>Reverse alignment</returns> private DeltaAlignment GetPreviousAlignment( IList <DeltaAlignment> alignments, DeltaAlignment currentAlignment) { DeltaAlignment deltaAlignment = null; int alignmentFirstEnd, alignmentSecondEnd, gapHigh, gapLow; int alignmentFirstStart = currentAlignment.FirstSequenceStart; int alignmentSecondStart = currentAlignment.SecondSequenceStart; int distance = (alignmentFirstStart < alignmentSecondStart) ? alignmentFirstStart : alignmentSecondStart; deltaAlignment = null; foreach (DeltaAlignment alignment in alignments) { if (currentAlignment.QueryDirection == alignment.QueryDirection) { alignmentFirstEnd = alignment.FirstSequenceEnd; alignmentSecondEnd = alignment.SecondSequenceEnd; if (alignmentFirstEnd <= alignmentFirstStart && alignmentSecondEnd <= alignmentSecondStart) { if ((alignmentFirstStart - alignmentFirstEnd) > (alignmentSecondStart - alignmentSecondEnd)) { gapHigh = alignmentFirstStart - alignmentFirstEnd; gapLow = alignmentSecondStart - alignmentSecondEnd; } else { gapLow = alignmentFirstStart - alignmentFirstEnd; gapHigh = alignmentSecondStart - alignmentSecondEnd; } if (gapHigh < BreakLength || ((gapLow * nucmerAligner.ValidScore) + ((gapHigh - gapLow) * nucmerAligner.SubstitutionScore)) >= 0) { deltaAlignment = alignment; break; } else if ((gapHigh << 1) - gapLow < distance) { deltaAlignment = alignment; distance = (gapHigh << 1) - gapLow; } } } } return(deltaAlignment); }
/// <summary> /// Create a new delta alignment /// </summary> /// <param name="referenceSequence">Reference sequence</param> /// <param name="querySequence">Query sequence</param> /// <param name="cluster">Cluster object</param> /// <param name="match">Match object</param> /// <returns>Newly created DeltaAlignment object</returns> internal static DeltaAlignment NewAlignment( ISequence referenceSequence, ISequence querySequence, Cluster cluster, MaxUniqueMatchExtension match) { DeltaAlignment deltaAlignment = new DeltaAlignment(referenceSequence, querySequence); deltaAlignment.FirstSequenceStart = match.FirstSequenceStart; deltaAlignment.SecondSequenceStart = match.SecondSequenceStart; deltaAlignment.FirstSequenceEnd = match.FirstSequenceStart + match.Length - 1; deltaAlignment.SecondSequenceEnd = match.SecondSequenceStart + match.Length - 1; deltaAlignment.QueryDirection = cluster.QueryDirection; return(deltaAlignment); }
/// <summary> /// Check if the cluster is shadowed (contained in alignment) /// </summary> /// <param name="alignments">List of alignment</param> /// <param name="currentCluster">current cluster</param> /// <param name="currentDeltaAlignment">Current delta alignment</param> /// <returns>Is cluster contained in alignment</returns> private static bool IsClusterShadowed( IList <DeltaAlignment> alignments, Cluster currentCluster, DeltaAlignment currentDeltaAlignment) { DeltaAlignment alignment = null; int counter; int firstSequenceStart = currentCluster.Matches.First().FirstSequenceStart; int firstSequenceEnd = currentCluster.Matches.Last().FirstSequenceStart + currentCluster.Matches.Last().Length - 1; int secondSequenceStart = currentCluster.Matches.First().SecondSequenceStart; int secondSequenceEnd = currentCluster.Matches.Last().SecondSequenceStart + currentCluster.Matches.Last().Length - 1; if (0 < alignments.Count) { for (counter = alignments.IndexOf(currentDeltaAlignment); counter >= 0; counter--) { alignment = alignments[counter]; if (alignment.QueryDirection == currentCluster.QueryDirection) { if ((alignment.FirstSequenceEnd >= firstSequenceEnd) && alignment.SecondSequenceEnd >= secondSequenceEnd && alignment.FirstSequenceStart <= firstSequenceStart && alignment.SecondSequenceStart <= secondSequenceStart) { break; } } } if (counter >= 0) { return(true); } } return(false); }
/// <summary> /// Extend the cluster forward /// </summary> /// <param name="referenceSequence">Reference sequence</param> /// <param name="querySequence">Query sequence</param> /// <param name="currentAlignment">current alignment object</param> /// <param name="targetReference">target position in reference sequence</param> /// <param name="targetQuery">target position in query sequence</param> /// <param name="methodName">Name of the method to be implemented</param> /// <returns>Was cluster extended forward</returns> private bool ExtendToNextSequence( ISequence referenceSequence, ISequence querySequence, DeltaAlignment currentAlignment, int targetReference, int targetQuery, int methodName) { int referenceDistance; int queryDistance; int diagonal; bool isClusterExtended; bool isOverflow = false; bool isDouble = false; diagonal = currentAlignment.Deltas.Count; referenceDistance = targetReference - currentAlignment.FirstSequenceEnd + 1; queryDistance = targetQuery - currentAlignment.SecondSequenceEnd + 1; // If the length in first sequence exceeds maximum length then extend // till score is optimized irrespective of length. if (referenceDistance > NUCmerAligner.MaximumAlignmentLength) { targetReference = currentAlignment.FirstSequenceEnd + NUCmerAligner.MaximumAlignmentLength + 1; isOverflow = true; methodName |= NUCmerAligner.OptimalFlag; } // If the length in second sequence exceeds maximum length then extend // till score is optimized irrespective of length. if (queryDistance > NUCmerAligner.MaximumAlignmentLength) { targetQuery = currentAlignment.SecondSequenceEnd + NUCmerAligner.MaximumAlignmentLength + 1; if (isOverflow) { isDouble = true; } else { isOverflow = true; } methodName |= NUCmerAligner.OptimalFlag; } if (isDouble) { methodName &= ~NUCmerAligner.SeqendFlag; } // Extend the sequence to next sequence (aligned/extended sequence) isClusterExtended = nucmerAligner.ExtendSequence( referenceSequence, currentAlignment.FirstSequenceEnd, ref targetReference, querySequence, currentAlignment.SecondSequenceEnd, ref targetQuery, currentAlignment.Deltas, methodName); if (isClusterExtended && isOverflow) { isClusterExtended = false; } if (diagonal < currentAlignment.Deltas.Count) { referenceDistance = (currentAlignment.FirstSequenceEnd - currentAlignment.FirstSequenceStart + 1) - currentAlignment.DeltaReferencePosition - 1; currentAlignment.Deltas[diagonal] += (currentAlignment.Deltas[diagonal] > 0) ? referenceDistance : -referenceDistance; // Adjust the delta reference position foreach (int deltaPosition in currentAlignment.Deltas) { currentAlignment.DeltaReferencePosition += (deltaPosition > 0) ? deltaPosition : Math.Abs(deltaPosition) - 1; } } currentAlignment.FirstSequenceEnd = targetReference; currentAlignment.SecondSequenceEnd = targetQuery; return(isClusterExtended); }
/// <summary> /// Extend the cluster backward /// </summary> /// <param name="referenceSequence">Reference sequence</param> /// <param name="querySequence">Query sequence</param> /// <param name="alignments">List of alignments</param> /// <param name="currentAlignment">current alignment object</param> /// <param name="targetAlignment">target alignment object</param> /// <returns>Was clusted extended backward</returns> private bool ExtendToPreviousSequence( ISequence referenceSequence, ISequence querySequence, IList <DeltaAlignment> alignments, DeltaAlignment currentAlignment, DeltaAlignment targetAlignment) { bool isClusterExtended = false; bool isOverflow = false; int targetReference; int targetQuery; int startReference; int startQuery; int methodName = NUCmerAligner.BackwardAlignFlag; if (alignments.Contains(targetAlignment)) { targetReference = targetAlignment.FirstSequenceEnd; targetQuery = targetAlignment.SecondSequenceEnd; } else { // If the target alignment is not found then extend till the // start of sequence (0th Symbol) targetReference = 0; targetQuery = 0; methodName |= NUCmerAligner.OptimalFlag; } // If the length in first sequence exceeds maximum length then extend // till score is optimized irrespective of length. if ((currentAlignment.FirstSequenceStart - targetReference + 1) > NUCmerAligner.MaximumAlignmentLength) { targetReference = currentAlignment.FirstSequenceStart - NUCmerAligner.MaximumAlignmentLength + 1; isOverflow = true; methodName |= NUCmerAligner.OptimalFlag; } // If the length in second sequence exceeds maximum length then extend // till score is optimized irrespective of length. if ((currentAlignment.SecondSequenceStart - targetQuery + 1) > NUCmerAligner.MaximumAlignmentLength) { targetQuery = currentAlignment.SecondSequenceStart = NUCmerAligner.MaximumAlignmentLength + 1; if (!isOverflow) { isOverflow = true; } methodName |= NUCmerAligner.OptimalFlag; } // Extend the sequence to previous sequence (aligned/extended sequence) isClusterExtended = nucmerAligner.ExtendSequence( referenceSequence, currentAlignment.FirstSequenceStart, ref targetReference, querySequence, currentAlignment.SecondSequenceStart, ref targetQuery, currentAlignment.Deltas, methodName); if (isOverflow || !alignments.Contains(targetAlignment)) { isClusterExtended = false; } if (isClusterExtended) { // Extend the sequence to next sequence (aligned/extended sequence) ExtendToNextSequence( referenceSequence, querySequence, targetAlignment, currentAlignment.FirstSequenceStart, currentAlignment.SecondSequenceStart, NUCmerAligner.ForcedForwardAlignFlag); targetAlignment.FirstSequenceEnd = currentAlignment.FirstSequenceEnd; targetAlignment.SecondSequenceEnd = currentAlignment.SecondSequenceEnd; } else { startReference = currentAlignment.FirstSequenceStart; startQuery = currentAlignment.SecondSequenceStart; nucmerAligner.ExtendSequence( referenceSequence, targetReference, ref startReference, querySequence, targetQuery, ref startQuery, currentAlignment.Deltas, NUCmerAligner.ForcedForwardAlignFlag); currentAlignment.FirstSequenceStart = targetReference; currentAlignment.SecondSequenceStart = targetQuery; // Adjust the delta reference position foreach (int deltaPosition in currentAlignment.Deltas) { currentAlignment.DeltaReferencePosition += (deltaPosition > 0) ? deltaPosition : Math.Abs(deltaPosition) - 1; } } return(isClusterExtended); }
/// <summary> /// Extend the cluster in synteny /// </summary> /// <param name="synteny">Synteny in which cluster needs to be extened.</param> /// <returns>List of delta alignments</returns> private IList <DeltaAlignment> ExtendClusters(Synteny synteny) { bool isClusterExtended = false; IList <DeltaAlignment> deltaAlignments = new List <DeltaAlignment>(); DeltaAlignment deltaAlignment = null; DeltaAlignment targetAlignment = null; Cluster currentCluster = null; Cluster targetCluster = synteny.Clusters.Last(); int targetReference; int targetQuery; int methodName = NUCmerAligner.ForwardAlignFlag; IList <Cluster> clusters = synteny.Clusters; // Sort the cluster by first sequence start clusters = SortCluster(clusters, FirstSequenceStart); IEnumerator <Cluster> previousCluster = clusters.GetEnumerator(); previousCluster.MoveNext(); IEnumerator <Cluster> cluster = clusters.GetEnumerator(); while (cluster.MoveNext()) { currentCluster = cluster.Current; if (!isClusterExtended && (currentCluster.IsFused || IsClusterShadowed(deltaAlignments, currentCluster, deltaAlignment))) { currentCluster.IsFused = true; previousCluster.MoveNext(); currentCluster = previousCluster.Current; continue; } // Extend the match foreach (MaxUniqueMatchExtension match in currentCluster.Matches) { if (isClusterExtended) { if (deltaAlignment.FirstSequenceEnd != match.FirstSequenceStart || deltaAlignment.SecondSequenceEnd != match.SecondSequenceStart) { continue; } deltaAlignment.FirstSequenceEnd += match.Length - 1; deltaAlignment.SecondSequenceEnd += match.Length - 1; } else { deltaAlignment = DeltaAlignment.NewAlignment( synteny.ReferenceSequence, synteny.QuerySequence, currentCluster, match); deltaAlignments.Add(deltaAlignment); // Find the MUM which is a good candidate for extension in reverse direction targetAlignment = GetPreviousAlignment(deltaAlignments, deltaAlignment); if (ExtendToPreviousSequence( synteny.ReferenceSequence, synteny.QuerySequence, deltaAlignments, deltaAlignment, targetAlignment)) { deltaAlignment = targetAlignment; } } methodName = NUCmerAligner.ForwardAlignFlag; if (currentCluster.Matches.IndexOf(match) < currentCluster.Matches.Count - 1) { // extend till the match in the current cluster MaxUniqueMatchExtension nextMatch = currentCluster.Matches[currentCluster.Matches.IndexOf(match) + 1]; targetReference = nextMatch.FirstSequenceStart; targetQuery = nextMatch.SecondSequenceStart; isClusterExtended = ExtendToNextSequence( synteny.ReferenceSequence, synteny.QuerySequence, deltaAlignment, targetReference, targetQuery, methodName); } else { // extend till next cluster targetReference = synteny.ReferenceSequence.Count - 1; targetQuery = synteny.QuerySequence.Count - 1; targetCluster = GetNextCluster( clusters, currentCluster, ref targetReference, ref targetQuery); if (!synteny.Clusters.Contains(targetCluster)) { methodName |= NUCmerAligner.OptimalFlag; } isClusterExtended = ExtendToNextSequence( synteny.ReferenceSequence, synteny.QuerySequence, deltaAlignment, targetReference, targetQuery, methodName); } } if (!synteny.Clusters.Contains(targetCluster)) { isClusterExtended = false; } currentCluster.IsFused = true; if (!isClusterExtended) { previousCluster.MoveNext(); currentCluster = previousCluster.Current; } else { currentCluster = targetCluster; } } return(deltaAlignments); }