Skip to content

Addition of indel retrieval#289

Open
elenikiachaki wants to merge 3 commits into
develfrom
fix280_retrieve_indels
Open

Addition of indel retrieval#289
elenikiachaki wants to merge 3 commits into
develfrom
fix280_retrieve_indels

Conversation

@elenikiachaki

Copy link
Copy Markdown
Collaborator

This PR addresses #280, adding support for retrieving and annotating in-frame indels in cancermuts.

Main changes

  • Created the protein variant parser function to parse all supported variants types.
  • Added a variant_types argument so users can request "missense", "deletion", "insertion" and/or "delins" variants.
  • Added indel retrieval support for cBioPortal, COSMIC and ClinVar.
  • Kept missense variants as the default, so existing usage remains unchanged.
  • Updated genomic metadata/liftover handling so indel genomic annotations can be converted between assemblies.
  • Extended gnomAD annotation to support indels when the genomic representation can be safely matched. Couldn't find a good solution for repeats and inversions and they are skipped.
  • Added tutorial_indels.py using RAD51C as an example.
  • Updated tutorial.md
  • Skipped REVEL retrieval for variants types other than missense

Notes

  • I followed the Ensembl VEP normalisation documentation VEP normalisation documentation for parsing the genomic mutations for gnomAD
  • For indels, it may be useful to optionally show the protein HGVS string in the metatable, since aa_position, ref_aa and alt_aa can be harder to interpret

Comment thread cancermuts/datasources.py Outdated
def __init__(self, *args, **kwargs):
super(StaticSource, self).__init__(*args, **kwargs)

def _protein_variant_parser(mutation, sequence, source):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I love having this function floating around - it breaks the consistency of the API for how we've developed it so far

so I propose this: we can have a DynamicMutationSource class that inherits from DynamicSource and defines this function as a class member, and then classes that need to use it have DynamicMutationSource as a base class

Comment thread cancermuts/datasources.py Outdated
super(StaticSource, self).__init__(*args, **kwargs)

def _protein_variant_parser(mutation, sequence, source):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given these definitions, would it possible for a variant to match more than one case for the same variant?

I was wondering if the order in which the variants are checked have any influence on their final classification

one idea could be to match all of them first and check if 2+ of them match. But then this is only necessary if we think it is possible that 2 or more can match

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, with the current fullmatch-based patterns, the variant classes should be mutually exclusive.

Comment thread cancermuts/datasources.py Outdated

raise ValueError(f"Unsupported protein mutation format: {mutation}")

def _normalise_variant_types(variant_types):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as previous re the location of this function

Comment thread cancermuts/datasources.py Outdated

raise ValueError(f"Unsupported protein mutation format: {mutation}")

def _normalise_variant_types(variant_types):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we change the name?

I don't think this function normalizes things - it just removes duplicates

Comment thread cancermuts/datasources.py Outdated
if invalid_variant_types:
raise ValueError(f"Invalid variant type(s): {invalid_variant_types}")

return variant_types

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is returning a set here intentional?

Comment thread cancermuts/datasources.py Outdated
Comment on lines +1617 to +1623
supported_genomic_annotation = (gm.is_snv
or gm.is_insdel
or gm.is_inversion
or gm.is_deletion
or gm.is_insertion
or gm.is_duplication
or gm.is_repeat)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a reason more we should think about a refactoring of metadata.GenomicMutation - it was ok when we were supporting 1/2 types but it's not very robust as it is

Comment thread cancermuts/datasources.py Outdated
or gm.is_duplication
or gm.is_repeat)

if gm.chr is None or not supported_genomic_annotation:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really get a None chromosome?

Comment thread cancermuts/datasources.py
Comment on lines +1634 to +1639
out_metadata["genomic_coordinates"].append([[gm.genome_build,
gm.chr,
gm.coord if gm.is_snv else gm.coord_start,
gm.coord if gm.is_snv else gm.coord_end,
gm.ref if gm.is_snv else None]
for gm in valid_gms])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above re refactoring

Comment thread cancermuts/datasources.py
this_df = data[data['edited_variant_id'] == v_str]

elif variant.is_insertion:
v_str = variant.definition

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we not specialize GenomicVariant.get_value_str() to return a format that makes sense to use for gnomad instead of doing all of the following?

Comment thread cancermuts/metadata.py
def __hash__(self):
return hash((self.source, self.chr, self.coord_start, self.coord_end, self.ref, self.genome_build))

class GenomicMutation(Metadata):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again - this is a bit convoluted as it is; let's give a thought if a refactoring would be better

@elenikiachaki

Copy link
Copy Markdown
Collaborator Author
  • GenomicMutation was refactored to use a mutation_type field instead of multiple flags (is_snv, is_deletion, etc.).

  • I removed the insdel case from GenomicMutation.get_value_str(fmt="gnomad"). Only SNVs can safely be converted into a gnomAD/VCF-style chrom-pos-ref-alt identifier with the information currently stored in GenomicMutation.

  • For gnomAD matching of indels, I follow VCF conventions. Since Cancermuts does not currently retrieve the reference genome sequence, I do not compare the genomic mutation ref to the VCF REF allele. Instead, matching is based on the information that is actually available (position, deleted interval length, and/or inserted sequence, depending on the variant type). Ambiguous matches are skipped. Duplications, inversions and repeats are currently not supported.

    VCF specification: https://samtools.github.io/hts-specs/VCFv4.2.pdf

  • I added a Genome Nexus lookup to recover HGVSg from cBioPortal genomic coordinates and alleles, since the cBioPortal endpoint we use does not provide gHGVS. If we prefer to avoid this additional dependency, I can revert this part and keep the previous behaviour.

  • I am not sure whether the current internal representation of protein insertions is the most intuitive for users (e.g. variant 482173 in metatable_indels.csv is not really easy to understand from ref and alt). An alternative would be to include the original HGVSp notation in the metatable or to change how we define ref and alt for insertions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants