Exemplo n.º 1
0
        private static int UpdateAndAddAlignment(BamAlignment finalRead, bool realignedOther,
                                                 BamAlignment finalReadOther,
                                                 List <BamAlignment> reads, INmCalculator nmCalculator, bool recalculateNm)
        {
            int nm = 0;

            if (finalRead != null)
            {
                if (realignedOther)
                {
                    finalRead.MatePosition = finalReadOther.Position;
                }

                if (recalculateNm)
                {
                    nm = nmCalculator.GetNm(finalRead);
                    AddNmTag(finalRead, nm);
                }

                reads.Add(finalRead);
            }

            return(nm);
        }
Exemplo n.º 2
0
        public List <BamAlignment> ExtractReads(PairResult pairResult, INmCalculator nmCalculator, bool doRealign = true, int readsToSilence = 0)
        {
            var pair = pairResult.ReadPair;

            if (pair.PairStatus == PairStatus.LeaveUntouched)
            {
                return(pair.GetAlignments().ToList());
            }
            var reads = new List <BamAlignment>();

            // TODO clean this up, should really not have two layers (pair result and readpair) here
            if (pairResult.ReadPair.Stitched)
            {
                const bool recalculateNm = true; // Always recalculate NM for stitched reads
                // TODO more explicitly assume/check that there is actually only one here
                foreach (var alignment in pairResult.Alignments)
                {
                    if (doRealign)
                    {
                        var finalReadR1 = RealignSingleAlignment(alignment, out var realignedR1);
                        pair.RealignedR1 = realignedR1;

                        SilenceReads(finalReadR1, null, readsToSilence, realignedR1, false);

                        pair.StitchedNm = UpdateAndAddAlignment(finalReadR1, false, null, reads, nmCalculator, recalculateNm);
                    }
                    else
                    {
                        SilenceReads(alignment, null, readsToSilence, false, false);

                        pair.StitchedNm = UpdateAndAddAlignment(alignment, false, null, reads, nmCalculator, recalculateNm);
                    }
                }

                return(reads);
            }
            if (pair.IsComplete(false) && (pair.PairStatus == PairStatus.Paired || pair.PairStatus == PairStatus.OffTarget))
            {
                var realignedR1 = false;

                var             realignedR2      = false;
                var             forcedSoftclipR1 = false;
                var             forcedSoftclipR2 = false;
                var             sketchy          = false;
                var             origRead1        = pair.Read1;
                var             origRead2        = pair.Read2;
                int?            r1Nm             = pair.Read1.GetIntTag("NM");
                int?            r2Nm             = pair.Read2.GetIntTag("NM");
                List <PreIndel> pairIndels       = null;

                if (pair.PairStatus == PairStatus.Paired)
                {
                    if (doRealign)
                    {
                        List <PreIndel> r1Indels = _hasExistingIndels && pairResult.R1Nm <= 2
                            ? pairResult.OriginalIndelsR1 ?? _indelTargetFinder.FindIndels(origRead1, _chromosome)
                            : _emptyList;
                        List <PreIndel> r2Indels = _hasExistingIndels && pairResult.R2Nm <= 2
                            ? pairResult.OriginalIndelsR2 ?? _indelTargetFinder.FindIndels(origRead2, _chromosome)
                            : _emptyList;

                        if (_pairAware && _hasExistingIndels && (r1Indels.Any() || r2Indels.Any()))
                        {
                            pairIndels = _finder.GetPairSpecificIndels(pair, r1Indels, r2Indels, ref r1Nm, ref r2Nm);
                        }

                        var confirmedAccepted = new List <HashableIndel>();

                        bool confirmedR1;
                        bool confirmedR2;


                        // TODO should we pay attention to whether one already has an indel and one doesn't, and realign/confirm the one that does, or that has the better one, first?
                        var try1Read1 = _evaluator.GetFinalAlignment(origRead1,
                                                                     out realignedR1, out forcedSoftclipR1, out confirmedR1, out sketchy, selectedIndels: pairIndels,
                                                                     existingIndels: r1Indels, confirmedAccepteds: confirmedAccepted, mateIndels: r2Indels);

                        pair.Read1 = try1Read1;
                        if ((realignedR1 || confirmedR1) && confirmedAccepted.Any())
                        {
                            pair.Read2 = _evaluator.GetFinalAlignment(origRead2,
                                                                      out realignedR2, out forcedSoftclipR2, out confirmedR2, out sketchy, selectedIndels: pairIndels,
                                                                      existingIndels: r2Indels, confirmedAccepteds: confirmedAccepted);
                        }
                        else
                        {
                            confirmedAccepted.Clear();
                            var try1Read2 = _evaluator.GetFinalAlignment(origRead2,
                                                                         out realignedR2, out forcedSoftclipR2, out confirmedR2, out sketchy, selectedIndels: pairIndels,
                                                                         existingIndels: r2Indels, confirmedAccepteds: confirmedAccepted, mateIndels: r1Indels);
                            pair.Read2 = try1Read2;

                            if ((realignedR2 || confirmedR2) && confirmedAccepted.Any())
                            {
                                pair.Read1 = _evaluator.GetFinalAlignment(origRead1,
                                                                          out realignedR1, out forcedSoftclipR1, out confirmedR1, out sketchy, selectedIndels: pairIndels,
                                                                          existingIndels: r1Indels, confirmedAccepteds: confirmedAccepted);
                            }
                        }

                        pairResult.R1Confirmed = confirmedR1;
                        pairResult.R2Confirmed = confirmedR2;
                    }

                    if (realignedR1 || realignedR2)
                    {
                        pair.Realigned = true;
                    }
                }

                pair.RealignedR1 = realignedR1;
                pair.RealignedR2 = realignedR2;

                // Silence realigned pair if needed
                SilenceReads(pair.Read1, pair.Read2, readsToSilence, realignedR1, realignedR2);
                // Silence original reads in case needed
                SilenceReads(origRead1, origRead2, readsToSilence, false, false);

                if (_allowedToStitch && !(forcedSoftclipR1 || forcedSoftclipR2) && (!_skipRestitchIfNothingChanged || (realignedR1 || realignedR2)))
                {
                    reads = _restitcher.GetRestitchedReads(pair, origRead1, origRead2, r1Nm, r2Nm, pairIndels != null, nmCalculator,
                                                           realignedR1 || realignedR2 || (r1Nm + r2Nm > 0), sketchy);

                    var isStitched = reads.Count == 1;
                    pair.Stitched             = isStitched;
                    pairResult.TriedStitching = true;

                    if (!isStitched)
                    {
                        reads.Clear();
                        // TODO looks like we are passing through EC twice - here and in the below foreach
                        HandleUnstitchedReads(pair, reads, realignedR1, realignedR2, nmCalculator);
                    }
                    foreach (var bamAlignment in reads)
                    {
                        _evidenceCollector.CollectEvidence(bamAlignment, true, isStitched, _chromosome);
                    }
                }
                else
                {
                    HandleUnstitchedReads(pair, reads, realignedR1, realignedR2, nmCalculator);
                }
            }
            else
            {
                if (doRealign)
                {
                    var finalReadR1 = RealignSingleAlignment(pair.Read1, out var realignedR1);
                    var finalReadR2 = RealignSingleAlignment(pair.Read2, out var realignedR2);
                    pair.RealignedR1 = realignedR1;
                    pair.RealignedR2 = realignedR2;
                    if (realignedR1 || realignedR2)
                    {
                        pair.Realigned = true;
                    }
                    SilenceReads(finalReadR1, finalReadR2, readsToSilence, realignedR1, realignedR2);
                    pair.Nm1 = UpdateAndAddAlignment(finalReadR1, realignedR2, finalReadR2, reads, nmCalculator, realignedR1);
                    pair.Nm2 = UpdateAndAddAlignment(finalReadR2, realignedR1, finalReadR1, reads, nmCalculator, realignedR2);
                }
                else
                {
                    SilenceReads(pair.Read1, pair.Read2, readsToSilence, false, false);

                    pair.Nm1 = UpdateAndAddAlignment(pair.Read1, false, pair.Read2, reads, nmCalculator, false);
                    pair.Nm2 = UpdateAndAddAlignment(pair.Read2, false, pair.Read1, reads, nmCalculator, false);
                }
            }


            return(reads);
        }
Exemplo n.º 3
0
        private void HandleUnstitchedReads(ReadPair pair, List <BamAlignment> reads, bool realignedR1, bool realignedR2, INmCalculator nmCalculator)
        {
            reads.Add(pair.Read1);
            reads.Add(pair.Read2);

            if (realignedR1)
            {
                pair.Read2.MatePosition = pair.Read1.Position;
                _evidenceCollector.CollectEvidence(pair.Read1, true, false, _chromosome);
                var nm = nmCalculator.GetNm(pair.Read1);
                pair.Nm1 = nm;

                AddNmTag(pair.Read1, nm);
            }

            if (realignedR2)
            {
                pair.Read1.MatePosition = pair.Read2.Position;
                _evidenceCollector.CollectEvidence(pair.Read2, true, false, _chromosome);
                var nm = nmCalculator.GetNm(pair.Read1);
                pair.Nm2 = nm;
                AddNmTag(pair.Read2, nm);
            }
        }
Exemplo n.º 4
0
        public List <BamAlignment> GetRestitchedReads(ReadPair pair, BamAlignment origRead1, BamAlignment origRead2, int?r1Nm, int?r2Nm, bool realignedAroundPairSpecific, INmCalculator nmCalculator, bool recalculateNm, bool realignmentIsSketchy = false)
        {
            var reads = new List <BamAlignment>();
            var badRestitchAfterPairSpecificRealign = false;

            var disagreeingReads = realignedAroundPairSpecific ? ShouldRestitch(pair) : null;

            if (disagreeingReads == null)
            {
                // TODO in some cases, we already tried stitching and then are realigning.
                // ... If nothing realigned, we don't need to try stitching again as we know it already failed.
                // ... However, in some cases, we haven't tried stitching yet as we were deferring until realignment.
                // ... For now, it's ok to leave this here, but know that we are wasting time in some cases trying to stitch the same pair again.
                int nmStitched    = 0;
                var stitchedReads = _stitchedPairHandler.ExtractReads(pair);
                if (stitchedReads.Count == 1)
                {
                    if (recalculateNm)
                    {
                        nmStitched      = nmCalculator.GetNm(stitchedReads[0]);
                        pair.StitchedNm = nmStitched;
                    }

                    if (realignedAroundPairSpecific)
                    {
                        // Check that the stitched read represents an overall improvement over the original reads
                        var scStitched = stitchedReads[0].CigarData.GetPrefixClip() +
                                         stitchedReads[0].CigarData.GetSuffixClip();
                        var r1Sc = origRead1.CigarData.GetPrefixClip() +
                                   origRead1.CigarData.GetSuffixClip();
                        var r2Sc = origRead2.CigarData.GetPrefixClip() +
                                   origRead2.CigarData.GetSuffixClip();

                        var origMess1    = r1Nm + r1Sc;
                        var origMess2    = r2Nm + r2Sc;
                        var stitchedMess = nmStitched + scStitched;

                        if (stitchedMess > (origMess1 + origMess2))
                        {
                            badRestitchAfterPairSpecificRealign = true;
                        }
                    }

                    if (!badRestitchAfterPairSpecificRealign)
                    {
                        _statusHandler.AddStatusCount($"Successfully stitched after realign (ps: {realignedAroundPairSpecific})");
                        _statusHandler.AddCombinedStatusStringTags("OC", pair.Read1, pair.Read2, stitchedReads[0]);
                        _statusHandler.AddCombinedStatusStringTags("OS", pair.Read1, pair.Read2, stitchedReads[0]);
                        _statusHandler.AddCombinedStatusStringTags("RS", pair.Read1, pair.Read2, stitchedReads[0]);
                        _statusHandler.AddCombinedStatusStringTags("RC", pair.Read1, pair.Read2, stitchedReads[0]);
                        _statusHandler.AddCombinedStatusStringTags("RX", pair.Read1, pair.Read2, stitchedReads[0]);

                        stitchedReads[0].ReplaceOrAddStringTag("SC",
                                                               pair.Read1.GetStringTag("SC") + pair.Read1.CigarData + "," + pair.Read2.CigarData);
                        stitchedReads[0].ReplaceOrAddIntTag("NM", nmStitched, true);

                        foreach (var tag in _tagsToKeepFromR1)
                        {
                            var r1Tag = pair.Read1.GetStringTag(tag);

                            if (r1Tag != null)
                            {
                                stitchedReads[0].ReplaceOrAddStringTag(tag, r1Tag);
                            }
                        }
                    }
                }
                else
                {
                    pair.FailForOtherReason = true;
                    if (realignmentIsSketchy)
                    {
                        badRestitchAfterPairSpecificRealign = true;
                    }
                    _statusHandler.AddStatusCount($"Failed stitching after realign (ps: {realignedAroundPairSpecific})");
                    _statusHandler.AppendStatusStringTag("RC", $"Bad after attempted pair-specific realign (ps: {realignedAroundPairSpecific})", origRead1);
                    _statusHandler.AppendStatusStringTag("RC", $"Bad after attempted pair-specific realign (ps: {realignedAroundPairSpecific})", origRead2);
                }

                if (badRestitchAfterPairSpecificRealign)
                {
                    _statusHandler.AddStatusCount($"Restitching was too messy after realign (ps: {realignedAroundPairSpecific})");
                    _statusHandler.AppendStatusStringTag("RC", "BadRestitchAfterPairSpecificRealign", origRead1);
                    _statusHandler.AppendStatusStringTag("RC", "BadRestitchAfterPairSpecificRealign", origRead2);

                    pair.BadRestitch = true;
                    // Go back to the originals
                    reads.Add(origRead1);
                    reads.Add(origRead2);
                }
                else
                {
                    reads = stitchedReads;
                }
            }
            else
            {
                pair.Disagree = true;
                return(disagreeingReads);
            }

            return(reads);
        }