private WittyerBndInternal([NotNull] WittyerType svType, [NotNull] IVcfVariant baseVariant, [NotNull] IInterval <uint> posInterval, [NotNull] IInterval <uint> ciPosInterval, [NotNull] IVcfVariant endOriginalVariant, [NotNull] IContigAndInterval endInterval, [NotNull] IInterval <uint> ciEndInterval, [NotNull] Winner win, [NotNull] IWittyerSample sample) { Contig = baseVariant.Contig; _posInterval = posInterval; EndInterval = endInterval; Sample = sample; OriginalVariant = baseVariant; EndOriginalVariant = endOriginalVariant; Win = win; VariantType = svType; CiPosInterval = ciPosInterval; CiEndInterval = ciEndInterval; }
private WittyerVariantInternal([NotNull] WittyerType svType, [NotNull] IVcfVariant baseVariant, [NotNull] IInterval <uint> baseInterval, [NotNull] Winner win, [NotNull] IContigAndInterval posInterval, [NotNull] IInterval <uint> ciPosInterval, [NotNull] IContigAndInterval endInterval, [NotNull] IInterval <uint> ciEndInterval, [NotNull] IWittyerSample sample) { OriginalVariant = baseVariant; Contig = baseVariant.Contig; VariantType = svType; Win = win; Sample = sample; _baseInterval = baseInterval; PosInterval = posInterval; EndInterval = endInterval; CiPosInterval = ciPosInterval; CiEndInterval = ciEndInterval; }
internal static IWittyerVariant Create([NotNull] IVcfVariant baseVariant, [CanBeNull] IVcfSample sample, [NotNull] WittyerType svType, [NotNull] IReadOnlyList <uint> bins, [CanBeNull] double?percentageDistance, uint basepairDistance) { // originalInterval is needed to adjust CIPOS and CIEND against for PD/BPD, but it won't be used for actual reflen and binning. var baseInterval = baseVariant.ToBedInterval(true, out var originalEnd, out var sharedFirstBase); if (baseInterval == null) { throw new InvalidOperationException( $"Expected failure of {nameof(WittyerUtils.ToBedInterval)} to throw, but didn't..."); } // CI intervals are always based on the original POS/END var posStart = baseVariant.Position; if (sharedFirstBase) { posStart++; } var ciPosInterval = posStart.ConvertPositionToCiInterval(baseVariant, WittyerConstants.Cipos); var ciEndInterval = originalEnd.ConvertPositionToCiInterval(baseVariant, WittyerConstants.Ciend); var baseStart = sharedFirstBase ? baseInterval.Start : baseInterval.Start + 1; // not sharing first base (ref site or complex types, etc) need adjustment // the pd/bpd intervals are based on the trimmed variant's coordinates. var(posInterval, endInterval) = WittyerUtils.GetPosAndEndInterval(baseVariant.Contig, percentageDistance, basepairDistance, ciPosInterval, baseStart, ciEndInterval, baseInterval.Stop); return(new WittyerVariantInternal(svType, baseVariant, baseInterval, Winner.Create(svType, baseInterval, bins), posInterval, ciPosInterval, endInterval, ciEndInterval, WittyerSample.CreateFromVariant(baseVariant, sample, svType == WittyerType.CopyNumberReference))); }
public static FailedReason?ParseFromVariant([NotNull] IVcfVariant variant, bool isCrossTypeOn, [CanBeNull] string sampleName, [CanBeNull] out WittyerType svType) { if (variant.IsRefSite() || IsRefCall(out var ploidy, out var cn, out var hasCn)) { svType = CopyNumberReference; return(null); } var hasSvTypeKey = variant.Info.TryGetValue(VcfConstants.SvTypeKey, out var svTypeStr); if (!hasSvTypeKey) { // todo: maybe we can allow small variants, which would not have SVTYPE throw new InvalidDataException( $"Following variant does not have {VcfConstants.SvTypeKey} info key:\n{variant}"); } svType = null; if (svTypeStr == SvTypeStrings.TranslocationBreakend) { // breakends can be IntraChromosomeBreakend and TranslocationBreakend, so can't tell from SVTYPE. var mate = variant is IBreakEnd cast ? cast.Mate : SimpleBreakEnd.TryParse(variant.GetSingleAlt()).GetOrThrow(); svType = variant.Contig.Equals(mate.Contig) ? IntraChromosomeBreakend : TranslocationBreakend; return(null); } if (!TryParseSvType(svTypeStr, out svType)) { // Not BND because of check above, and if not parsable and not CNV, it's something we don't know. if (svTypeStr != SvTypeStrings.Cnv) { throw new InvalidDataException($"Cannot recognize SVTYPE of {svTypeStr}"); } } else if (!svType.HasBaseLevelStats) { // If INV or INS or whatever that doesn't need to look for CN, return. return(null); } if (!hasCn) { return(svType == null ? FailedReason.CnvWithoutCn : default(FailedReason?)); // DEL or DUP without CN } // At this point, it is CNV with CN or DEL/DUP with CN, which are also considered CNV if (cn == null) { // has CN, but can't parse. svType = null; // clear out SVTYPE=DEL/DUP return(FailedReason.UndeterminedCn); } svType = GetSvType(cn.Value); return(null); WittyerType GetSvType(int cnValue) => cnValue < ploidy ? (isCrossTypeOn ? Deletion : CopyNumberLoss) : (isCrossTypeOn ? Duplication : CopyNumberGain); bool IsRefCall(out int ploidyP, out int?cnP, out bool hasCnP) { ploidyP = 2; cnP = null; hasCnP = false; //if not refsite and no sample field, not a refcall if (variant.Samples.Count == 0) { return(false); } var sample = sampleName == null ? variant.Samples[0] : variant.Samples[sampleName]; hasCnP = sample.SampleDictionary.TryGetValue(VcfConstants.CnSampleFieldKey, out var cnString); var isGt = sample.SampleDictionary.TryGetValue(VcfConstants.GenotypeKey, out var gt); if (hasCnP && int.TryParse(cnString, out var i)) { cnP = i; } if (!isGt) { return(hasCnP && cnString == "2"); } //todo: refining how to deal with ploidy. Also here we don't deal with LOH. assuming CN = ploidy is ref var gtArray = gt.Split(VcfConstants.GtPhasedValueDelimiter[0], VcfConstants.GtUnphasedValueDelimiter[0]); ploidyP = gtArray.Length; return(cnP == null?gtArray.All(alleleIndex => alleleIndex == "0") : cnP.Value == ploidyP); } }
internal static bool TryParseSvType(string svType, out WittyerType type) => AllSvTypesStrings.TryGetValue(svType, out type);
public static bool TryParse(string name, [CanBeNull] out WittyerType type) => AllTypesStrings.TryGetValue(name, out type);
internal static IWittyerBnd Create([NotNull] IVcfVariant first, [CanBeNull] IVcfSample originalSample, [NotNull] WittyerType svType, [NotNull] IReadOnlyList <uint> bins, uint bpd, double?percentageDistance, [NotNull] IVcfVariant second) { if (!ReferenceEquals(first, second)) { (first, second) = FindBndEntriesOrder(in first, in second); } var ciPosInterval = first.Position.ConvertPositionToCiInterval(first, WittyerConstants.Cipos); var ciEndInterval = ReferenceEquals(first, second) ? ciPosInterval // same variant means same intervals. : second.Position.ConvertPositionToCiInterval(second, WittyerConstants.Cipos); IContigAndInterval posInterval, endInterval; if (ReferenceEquals(first, second)) // insertions need trimming and stuff. { var trimmed = first.TryNormalizeVariant(VariantNormalizer.TrimCommonBases, 0).GetOrThrow(); var tuple = (bpd, bpd); var(posStart, posStop) = trimmed.Position.ConvertPositionToCiInterval(tuple); WittyerUtils.GetBetterInterval(ciPosInterval, ref posStart, ref posStop); posInterval = endInterval = ContigAndInterval.Create(first.Contig, posStart, posStop); } else { (posInterval, endInterval) = WittyerUtils.GetPosAndEndInterval(first.Contig, svType == WittyerType.IntraChromosomeBreakend ? percentageDistance : null, bpd, ciPosInterval, first.Position, ciEndInterval, second.Position, second.Contig); } var winner = GetWinner(); var sample = WittyerSample.CreateFromVariant(first, originalSample, false); return(new WittyerBndInternal(svType, first, posInterval, ciPosInterval, second, endInterval, ciEndInterval, winner, sample)); (IVcfVariant first, IVcfVariant second) FindBndEntriesOrder(in IVcfVariant variantA, in IVcfVariant variantB) => ContigAndPositionComparer.Default.Compare(variantA, variantB) > 0 ? (variantB, variantA) : (variantA, variantB); Winner GetWinner() { if (svType == WittyerType.TranslocationBreakend) { return(Winner.Create(svType)); } IInterval <uint> bedInterval; if (svType == WittyerType.Insertion) { bedInterval = GetInsertionInterval(first); } else { var start = first.Position; if (start > 0) { start--; } bedInterval = BedInterval.Create(start, second.Position); } return(Winner.Create(svType, bedInterval, bins)); } }
internal static IWittyerBnd CreateInsertion([NotNull] IVcfVariant first, [CanBeNull] IVcfSample originalSample, [NotNull] WittyerType svType, [NotNull] IReadOnlyList <uint> bins, uint bpd, double?pd) => Create(first, originalSample, svType, bins, bpd, pd, first);