import _ from 'lodash' ; import { TranscriptConsequenceSummary , VariantAnnotation , VariantAnnotationSummary , } from 'genome-nexus-ts-api-client' ; import { Mutation } from '../model/Mutation' ; import { genomicLocationString , extractGenomicLocation } from './MutationUtils' ; import { getMutationTypeFromProteinChange , getProteinPositionFromProteinChange , } from './ProteinChangeUtils' ; export function resolveDefaultsForMissingValues ( mutations ) { resolveMissingProteinPositions ( mutations ) ; resolveMissingMutationTypes ( mutations ) ; } /**
 * Tries resolving the protein position value from the protein change string.
 */ export function resolveMissingProteinPositions ( mutations ) { mutations . forEach ( mutation => { if ( mutation . proteinPosStart === undefined && mutation . proteinPosEnd === undefined ) { const proteinChange = mutation . proteinChange || mutation . aminoAcidChange ; const proteinPosition = getProteinPositionFromProteinChange ( proteinChange ) ; if ( proteinPosition ) { mutation . proteinPosStart = proteinPosition . start ; mutation . proteinPosEnd = proteinPosition . end ; } } } ) ; } export function resolveMissingMutationTypes ( mutations ) { mutations . forEach ( mutation => { if ( ! mutation . mutationType ) { mutation . mutationType = getMutationTypeFromProteinChange ( mutation . proteinChange || mutation . aminoAcidChange ) || '' ; } } ) ; } export function annotateMutations ( mutations , indexedVariantAnnotations ) { if ( _ . every ( mutations , mutation => { return _ . has ( mutation , 'proteinChange' ) ; } ) ) { return mutations . map ( mutation => annotateMutation ( mutation , indexedVariantAnnotations , false ) ) ; } else { return mutations . map ( mutation => annotateMutation ( mutation , indexedVariantAnnotations , true ) ) ; } } /**
 * Returns those mutations where the most significant impact on a canonical
 * transcript is affecting the given transcript id.
 *
 * TODO: Once the comoponents downstream are improved to handle multiple
 * annotations we can change this function to return all mutations that have
 * any effect on the given transcript.
 */ export function filterMutationByTranscriptId ( mutation , ensemblTranscriptId , indexedVariantAnnotations ) { const genomicLocation = extractGenomicLocation ( mutation ) ; const variantAnnotation = genomicLocation ? indexedVariantAnnotations [ genomicLocationString ( genomicLocation ) ] : undefined ; if ( variantAnnotation ) { return ( variantAnnotation . annotation_summary . canonicalTranscriptId === ensemblTranscriptId ) ; } else { return false ; } } export function getMutationByTranscriptId < T extends Mutation > ( mutation , ensemblTranscriptId , indexedVariantAnnotations , isCanonicalTranscript = false , skipAnnotationForCanonicalTranscript = false ) { const genomicLocation = extractGenomicLocation ( mutation ) ; const variantAnnotation = genomicLocation ? indexedVariantAnnotations [ genomicLocationString ( genomicLocation ) ] : undefined ; const transcriptConsequenceSummaries = variantAnnotation && variantAnnotation . annotation_summary && variantAnnotation . annotation_summary . transcriptConsequenceSummaries && variantAnnotation . annotation_summary . transcriptConsequenceSummaries . filter ( ( tc ) => tc . transcriptId === ensemblTranscriptId ) ; if ( isCanonicalTranscript && skipAnnotationForCanonicalTranscript ) { return mutation ; } if ( variantAnnotation && transcriptConsequenceSummaries && transcriptConsequenceSummaries . length > 0 ) { const transcriptConsequenceSummary = transcriptConsequenceSummaries [ 0 ] ; const annotatedMutation = getAnnotatedMutationFromAnnotationSummary ( mutation , variantAnnotation . annotation_summary , transcriptConsequenceSummary , isCanonicalTranscript , ! skipAnnotationForCanonicalTranscript ) ; if ( ! annotatedMutation . proteinChange ) { annotatedMutation . proteinChange = '' ; } return annotatedMutation as T ; } else { return undefined ; } } export function getAnnotatedMutationFromAnnotationSummary ( mutation , annotationSummary , transcriptConsequenceSummary , isCanonicalTranscript , shouldOverwriteByAnnotatedMutation = false ) { const annotatedMutation = initAnnotatedMutation ( mutation ) ; if ( ! isCanonicalTranscript || shouldOverwriteByAnnotatedMutation ) { annotatedMutation . variantType = annotationSummary . variantType ; annotatedMutation . proteinChange = transcriptConsequenceSummary . hgvspShort ; if ( annotatedMutation . proteinChange ) { annotatedMutation . proteinChange = annotatedMutation . proteinChange . replace ( /^p./ , '' ) ; } annotatedMutation . mutationType = transcriptConsequenceSummary . variantClassification ; if ( transcriptConsequenceSummary . proteinPosition ) { annotatedMutation . proteinPosStart = transcriptConsequenceSummary . proteinPosition . start ; annotatedMutation . proteinPosEnd = transcriptConsequenceSummary . proteinPosition . end ; } else { annotatedMutation . proteinPosStart = undefined ; annotatedMutation . proteinPosEnd = undefined ; } } const entrezGeneId = parseInt ( transcriptConsequenceSummary . entrezGeneId , 10 ) ; annotatedMutation . gene = { ... annotatedMutation . gene , hugoGeneSymbol : ( isCanonicalTranscript && annotatedMutation . gene && annotatedMutation . gene . hugoGeneSymbol ) || transcriptConsequenceSummary . hugoGeneSymbol , entrezGeneId : ( annotatedMutation . gene && annotatedMutation . gene . entrezGeneId ) || entrezGeneId , } ; return annotatedMutation ; } export function getMutationsByTranscriptId < T extends Mutation > ( mutations , ensemblTranscriptId , indexedVariantAnnotations , isCanonicalTranscript ? , skipAnnotationForCanonicalTranscript = false ) { const fusionMutation = getFusionMutations ( mutations ) ; const annotatableMutations = _ . difference ( mutations , fusionMutation ) ; return _ . concat ( _ . compact ( annotatableMutations . map ( mutation => getMutationByTranscriptId ( mutation , ensemblTranscriptId , indexedVariantAnnotations , isCanonicalTranscript , skipAnnotationForCanonicalTranscript ) ) ) , fusionMutation ) as T [ ] ; } export function filterMutationsByTranscriptId ( mutations , ensemblTranscriptId , indexedVariantAnnotations ) { return mutations . filter ( mutation => filterMutationByTranscriptId ( mutation , ensemblTranscriptId , indexedVariantAnnotations ) ) ; } export function annotateMutation ( mutation , indexedVariantAnnotations , shouldOverwriteByAnnotatedMutation ? ) { const genomicLocation = extractGenomicLocation ( mutation ) ; const variantAnnotation = genomicLocation ? indexedVariantAnnotations [ genomicLocationString ( genomicLocation ) ] : undefined ; let canonicalTranscript ; const annotationSummary = variantAnnotation ?. annotation_summary ; if ( annotationSummary ) { canonicalTranscript = findCanonicalTranscript ( annotationSummary ) ; } if ( annotationSummary && canonicalTranscript ) { return getAnnotatedMutationFromAnnotationSummary ( mutation , annotationSummary , canonicalTranscript , true , shouldOverwriteByAnnotatedMutation ) ; } else { return initAnnotatedMutation ( mutation ) ; } } export function initAnnotatedMutation ( mutation ) { return { ... mutation , variantType : mutation . variantType || '' , gene : mutation . gene || { hugoGeneSymbol : '' , } , proteinChange : mutation . proteinChange || '' , mutationType : mutation . mutationType || '' , } ; } export function findCanonicalTranscript ( annotationSummary ) { let canonical = _ . find ( annotationSummary . transcriptConsequenceSummaries , transcriptConsequenceSummary => transcriptConsequenceSummary . transcriptId === annotationSummary . canonicalTranscriptId ) ; if ( ! canonical ) { canonical = annotationSummary . transcriptConsequenceSummaries . length > 0 ? annotationSummary . transcriptConsequenceSummaries [ 0 ] : undefined ; } return canonical ; } export function indexAnnotationsByGenomicLocation ( variantAnnotations ) { return _ . keyBy ( variantAnnotations , annotation => annotation . originalVariantQuery ? annotation . originalVariantQuery : genomicLocationStringFromVariantAnnotation ( annotation ) ) ; } export function genomicLocationStringFromVariantAnnotation ( annotation ) { const chromosome = annotation . seq_region_name ; const start = annotation . start ; const end = annotation . end ; const referenceAllele = annotation . allele_string . split ( '/' ) [ 0 ] ; const variantAllele = annotation . allele_string . split ( '/' ) [ 1 ] ; return genomicLocationString ( { chromosome , start , end , referenceAllele , variantAllele , } ) ; } export function getFusionMutations < T extends Mutation > ( mutations ) { const fusionRegex = new RegExp ( 'fusion' , 'i' ) ; return mutations . filter ( ( m ) => m . mutationType && fusionRegex . test ( m . mutationType ) ) ; }