public static void MergeSegmentsUsingExcludedIntervals(ref List<CanvasSegment> segments, int MinimumCallSize,
Dictionary<string, List<GenomicBin>> excludedIntervals)
{
if (!segments.Any()) return;
// Assimilate short segments into the *best* available neighbor:
List<CanvasSegment> mergedSegments = new List<CanvasSegment>();
int segmentIndex = 0;
while (segmentIndex < segments.Count)
{
if (segments[segmentIndex].End - segments[segmentIndex].Begin >= MinimumCallSize)
{
mergedSegments.Add(segments[segmentIndex]);
segmentIndex++;
continue;
}
int prevIndex = -1;
double prevQ = 0;
// Look back for a segment:
for (int checkIndex = segmentIndex - 1; checkIndex > 0; checkIndex--)
{
// Stop, if you jump to another chromosome, or cross a forbidden interval:
if (segments[checkIndex].Chr != segments[segmentIndex].Chr) break;
if (segments[checkIndex].End - segments[checkIndex].Begin < MinimumCallSize) continue;
if (IsForbiddenInterval(segments[checkIndex].Chr, segments[checkIndex].End, segments[segmentIndex].Begin, excludedIntervals)) break;
prevIndex = checkIndex;
prevQ = segments[checkIndex].QScore;
break;
}
// Look forward for a segment:
int nextIndex = -1;
double nextQ = 0;
for (int checkIndex = segmentIndex + 1; checkIndex < segments.Count; checkIndex++)
{
if (segments[checkIndex].Chr != segments[segmentIndex].Chr) break;
if (segments[checkIndex].End - segments[checkIndex].Begin < MinimumCallSize) continue;
if (IsForbiddenInterval(segments[checkIndex].Chr, segments[segmentIndex].End, segments[checkIndex].Begin, excludedIntervals)) break;
nextIndex = checkIndex;
nextQ = segments[checkIndex].QScore;
break;
}
if (prevQ > 0 && prevQ >= nextQ)
{
// segments[prevIndex] assimilates segments[prevIndex+1...segmentIndex].
// Assimilation of previous segments was already done, so we just need to assimilate this one:
segments[prevIndex].MergeIn(segments[segmentIndex]);
segmentIndex++;
continue;
}
if (nextQ > 0)
{
// segments[nextIndex] assimilates segments[segmentIndex...nextIndex - 1]
for (int tempIndex = segmentIndex; tempIndex < nextIndex; tempIndex++)
{
segments[nextIndex].MergeIn(segments[tempIndex]);
}
segmentIndex = nextIndex;
continue;
}
mergedSegments.Add(segments[segmentIndex]);
segmentIndex++;
}
segments = mergedSegments;
// Now, merge together adjacent segments with same calls!
mergedSegments = new List<CanvasSegment>();
CanvasSegment lastSegment = segments[0];
mergedSegments.Add(lastSegment);
segmentIndex = 1;
while (segmentIndex < segments.Count)
{
// Assimilate an adjacent segment with the same copy number call:
if (lastSegment.copyNumber == segments[segmentIndex].copyNumber && lastSegment.Chr == segments[segmentIndex].Chr &&
!IsForbiddenInterval(lastSegment.Chr, lastSegment.End, segments[segmentIndex].Begin, excludedIntervals))
{
lastSegment.MergeIn(segments[segmentIndex]);
segmentIndex++;
continue;
}
lastSegment = segments[segmentIndex];
mergedSegments.Add(segments[segmentIndex]);
segmentIndex++;
}
segments = mergedSegments;
}