Skip to content

Commit

Permalink
Add --add_supporting_other_alt_color flag for to modify colors for th…
Browse files Browse the repository at this point in the history
…e 5th channel.

PiperOrigin-RevId: 311574586
  • Loading branch information
gunjanbaid authored and copybara-github committed May 14, 2020
1 parent d343b89 commit 7a68aee
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 21 deletions.
6 changes: 6 additions & 0 deletions deepvariant/make_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@
'sort_by_haplotypes', False,
'If True, reads are sorted by haplotypes (using HP tag), '
'parse_sam_aux_fields has to be set for this to work.')
flags.DEFINE_bool(
'add_supporting_other_alt_color', False,
'If True, reads supporting an alt not represented in the '
'pileup image are colored differently for multiallelics.')

# ---------------------------------------------------------------------------
# Selecting variants of specific types (e.g., SNPs)
Expand Down Expand Up @@ -478,6 +482,8 @@ def default_options(add_flags=True, flags_obj=None):
options.pic_options.width = flags_obj.pileup_image_width

options.pic_options.alt_aligned_pileup = flags_obj.alt_aligned_pileup
if flags_obj.add_supporting_other_alt_color:
options.pic_options.other_allele_supporting_read_alpha = 0.3

if flags_obj.select_variant_types:
options.select_variant_types[:] = flags_obj.select_variant_types.split()
Expand Down
14 changes: 14 additions & 0 deletions deepvariant/make_examples_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,20 @@ def test_gvcf_output_enabled_is_true_with_gvcf_flag(self):
options = make_examples.default_options(add_flags=True)
self.assertTrue(make_examples.gvcf_output_enabled(options))

@flagsaver.FlagSaver
def test_add_supporting_other_alt_color(self):
FLAGS.mode = 'training'
FLAGS.gvcf = ''
FLAGS.reads = ''
FLAGS.ref = ''
FLAGS.examples = ''
FLAGS.add_supporting_other_alt_color = True
options = make_examples.default_options(add_flags=True)
self.assertAlmostEqual(
options.pic_options.other_allele_supporting_read_alpha, 0.3)
self.assertAlmostEqual(options.pic_options.allele_unsupporting_read_alpha,
0.6)

def test_validate_ref_contig_coverage(self):
ref_contigs = _make_contigs([('1', 100), ('2', 100)])

Expand Down
1 change: 1 addition & 0 deletions deepvariant/pileup_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def default_options(read_requirements=None):
base_color_stride=70,
allele_supporting_read_alpha=1.0,
allele_unsupporting_read_alpha=0.6,
other_allele_supporting_read_alpha=0.6,
reference_matching_read_alpha=0.2,
reference_mismatching_read_alpha=1.0,
indel_anchoring_base_char='*',
Expand Down
44 changes: 31 additions & 13 deletions deepvariant/pileup_image_native.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,36 @@ using tensorflow::uint8;

namespace {

// Does this read support one of the alternative alleles?
inline bool ReadSupportsAlt(const DeepVariantCall& dv_call,
const Read& read,
const std::vector<string>& alt_alleles) {
// Does this read support ref, one of the alternative alleles, or an allele we
// aren't considering?
inline int ReadSupportsAlt(const DeepVariantCall& dv_call, const Read& read,
const std::vector<string>& alt_alleles) {
string key = (read.fragment_name() + "/" +
std::to_string(read.read_number()));
for (const string& alt_allele : alt_alleles) {

// Iterate over all alts, not just alt_alleles.
for (const string& alt_allele : dv_call.variant().alternate_bases()) {
const auto& allele_support = dv_call.allele_support();
const bool alt_allele_present_in_call =
allele_support.find(alt_allele) != allele_support.cend();

if (alt_allele_present_in_call) {
const auto& supp_read_names = allele_support.at(alt_allele).read_names();
for (const string& read_name : supp_read_names) {
if (read_name == key) return true;
const bool alt_in_alt_alleles =
std::find(alt_alleles.begin(), alt_alleles.end(), alt_allele) !=
alt_alleles.end();
// Read can support an alt we are currently considering (1), a different
// alt not present in alt_alleles (2), or ref (0).
if (read_name == key && alt_in_alt_alleles) {
return 1;
} else if (read_name == key && !alt_in_alt_alleles) {
return 2;
}
}
}
}
return false;
return 0;
}

} // namespace
Expand Down Expand Up @@ -149,10 +161,16 @@ int PileupImageEncoderNative::MatchesRefColor(bool base_matches_ref) const {
return static_cast<int>(kMaxPixelValueAsFloat * alpha);
}

int PileupImageEncoderNative::SupportsAltColor(bool read_supports_alt) const {
float alpha = (read_supports_alt ?
options_.allele_supporting_read_alpha() :
options_.allele_unsupporting_read_alpha());
int PileupImageEncoderNative::SupportsAltColor(int read_supports_alt) const {
float alpha;
if (read_supports_alt == 0) {
alpha = options_.allele_unsupporting_read_alpha();
} else if (read_supports_alt == 1) {
alpha = options_.allele_supporting_read_alpha();
} else {
CHECK_EQ(read_supports_alt, 2) << "read_supports_alt can only be 0/1/2.";
alpha = options_.other_allele_supporting_read_alpha();
}
return static_cast<int>(kMaxPixelValueAsFloat * alpha);
}

Expand Down Expand Up @@ -184,7 +202,7 @@ PileupImageEncoderNative::EncodeRead(const DeepVariantCall& dv_call,
const vector<string>& alt_alleles) {
ImageRow img_row(ref_bases.size(),
options_.num_channels());
const bool supports_alt = ReadSupportsAlt(dv_call, read, alt_alleles);
const int supports_alt = ReadSupportsAlt(dv_call, read, alt_alleles);
const int mapping_quality = read.alignment().mapping_quality();
const bool is_forward_strand = !read.alignment().position().reverse_strand();
const uint8 alt_color = SupportsAltColor(supports_alt);
Expand Down Expand Up @@ -336,7 +354,7 @@ PileupImageEncoderNative::EncodeReference(const string& ref_bases) {
uint8 mapping_quality_color = MappingQualityColor(ref_qual);
// We use "+" strand color for the reference.
uint8 strand_color = StrandColor(true);
uint8 alt_color = SupportsAltColor(false);
uint8 alt_color = SupportsAltColor(0);
uint8 ref_color = MatchesRefColor(true);

ImageRow img_row(ref_bases.size(),
Expand Down
2 changes: 1 addition & 1 deletion deepvariant/pileup_image_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class PileupImageEncoderNative {
// Get the strand pixel color (int) for a positive strand observation.
int StrandColor(bool on_positive_strand) const;
// Get the pixel color (int) for a read that supports an alt allele.
int SupportsAltColor(bool read_supports_alt) const;
int SupportsAltColor(int read_supports_alt) const;
// Get the pixel color (int) for a read that matches ref.
int MatchesRefColor(bool base_matches_ref) const;
// Get the pixel color (int) for a base read quality.
Expand Down
61 changes: 56 additions & 5 deletions deepvariant/pileup_image_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,19 @@ def test_strand_color(self, on_positive_strand, expected_color):
self.assertAlmostEqual(pie.strand_color(on_positive_strand), expected_color)

@parameterized.parameters(
(False, int(254.0 * 0.2)),
(True, int(254.0 * 0.1)),
(0, int(254.0 * 0.2), 0.6),
(1, int(254.0 * 0.1), 0.6),
(2, int(254.0 * 0.6), 0.6),
(0, int(254.0 * 0.2), 0.3),
(1, int(254.0 * 0.1), 0.3),
(2, int(254.0 * 0.3), 0.3),
)
def test_supports_alt_color(self, supports_alt, expected_color):
def test_supports_alt_color(self, supports_alt, expected_color,
other_allele_supporting_read_alpha):
pie = _make_encoder(
allele_supporting_read_alpha=0.1, allele_unsupporting_read_alpha=0.2)
allele_supporting_read_alpha=0.1,
allele_unsupporting_read_alpha=0.2,
other_allele_supporting_read_alpha=other_allele_supporting_read_alpha)
self.assertAlmostEqual(pie.supports_alt_color(supports_alt), expected_color)

@parameterized.parameters(
Expand Down Expand Up @@ -472,7 +479,7 @@ def test_read_support_is_respected(self, read_name, read_number, alt_allele,
start=10,
end=11,
reference_bases='A',
alternate_bases=[alt_allele]),
alternate_bases=['C', 'G']),
allele_support={
'C': _supporting_reads('read1/1', 'read3/2'),
'G': _supporting_reads('read2/1', 'read2/2'),
Expand All @@ -495,6 +502,50 @@ def test_read_support_is_respected(self, read_name, read_number, alt_allele,

self.assertEqual(list(actual[0, 1]), expected)

@parameterized.parameters(
('read1', 1, 'C', 'C', True, int(254.0 * 1.0)),
# This read isn't present in allele support for 'C'.
('read1', 2, 'C', 'C', True, int(254.0 * 0.6)),
('read2', 1, 'C', 'G', True, int(254.0 * 0.3)),
('read1', 1, 'C', 'C', False, int(254.0 * 1.0)),
# This read isn't present in allele support for 'C'.
('read1', 2, 'C', 'C', False, int(254.0 * 0.6)),
('read2', 1, 'C', 'G', False, int(254.0 * 0.6)),
)
def test_read_support_multiallelic(self, read_name, read_number, alt_allele,
read_base, add_supporting_other_alt_color,
expected_color):
"""supports_alt is encoded as the 5th channel out of the 7 channels."""
dv_call = deepvariant_pb2.DeepVariantCall(
variant=variants_pb2.Variant(
reference_name='chr1',
start=10,
end=11,
reference_bases='A',
alternate_bases=['C', 'G']),
allele_support={
'C': _supporting_reads('read1/1'),
'G': _supporting_reads('read2/1', 'read2/2'),
})
read = test_utils.make_read(
read_base,
start=dv_call.variant.start,
cigar='1M',
quals=[50],
name=read_name)
read.read_number = read_number

if add_supporting_other_alt_color:
other_allele_supporting_read_alpha = 0.3
else:
other_allele_supporting_read_alpha = 0.6

pie = _make_encoder(
other_allele_supporting_read_alpha=other_allele_supporting_read_alpha)
actual = pie.encode_read(dv_call, 'TAT', read, dv_call.variant.start - 1,
alt_allele)
self.assertEqual(actual[0, 1, 4], expected_color)


class PileupImageCreatorEncodePileupTest(parameterized.TestCase):
"""Tests of PileupImageCreator build_pileup routine."""
Expand Down
4 changes: 3 additions & 1 deletion deepvariant/protos/deepvariant.proto
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ message VariantLabelerOptions {
}

// Options to control how our we construct pileup images.
// Next ID: 32.
// Next ID: 33.
message PileupImageOptions {
// redacted
// The height, in pixels, of the pileup image we'll construct.
Expand Down Expand Up @@ -394,6 +394,8 @@ message PileupImageOptions {

// The alpha to apply to reads that support our alt alleles.
float allele_supporting_read_alpha = 9;
// The alpha to apply to reads that support the other alt allele.
float other_allele_supporting_read_alpha = 32;
// The alpha to apply to reads that do not support our alt alleles.
float allele_unsupporting_read_alpha = 10;
// The alpha to apply to a base that matches the reference sequence.
Expand Down
2 changes: 1 addition & 1 deletion deepvariant/python/pileup_image_native.clif
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ from "deepvariant/pileup_image_native.h":
self, on_positive_strand: bool) -> int

def `SupportsAltColor` as supports_alt_color(
self, read_supports_alt: bool) -> int
self, read_supports_alt: int) -> int

def `MatchesRefColor` as matches_ref_color(
self, base_matches_ref: bool) -> int
Expand Down

0 comments on commit 7a68aee

Please sign in to comment.