@@ -3,7 +3,7 @@ const express = require('express');
33
44const router = express . Router ( { mergeParams : true } ) ;
55
6- const { Op , literal} = require ( 'sequelize' ) ;
6+ const { literal} = require ( 'sequelize' ) ;
77const db = require ( '../../models' ) ;
88const logger = require ( '../../log' ) ;
99
@@ -13,6 +13,7 @@ const KBMATCHEXCLUDE = ['id', 'reportId', 'variantId', 'deletedAt', 'updatedBy']
1313const OBSVARANNOTEXCLUDE = KBMATCHEXCLUDE ;
1414const STATEMENTEXCLUDE = [ 'id' , 'reportId' , 'deletedAt' , 'updatedBy' ] ;
1515const MUTATION_REGEX = '^([^\\s]+)(\\s)(mutation[s]?)?(missense)?$' ;
16+ const MSI_CUTOFF = 20 ;
1617
1718const getVariants = async ( tableName , variantType , reportId ) => {
1819 return db . models [ tableName ] . scope ( 'extended' ) . findAll ( {
@@ -38,87 +39,66 @@ const getVariants = async (tableName, variantType, reportId) => {
3839} ;
3940
4041const unknownSignificanceIncludes = [ 'mut' ] ;
41- const signatureVariant = [ 'tmb' , 'msi' , 'sigv' ] ;
42-
43- const unknownSignificanceGeneFilter = {
44- [ Op . or ] : [ { oncogene : true } , { tumourSuppressor : true } , { cancerGeneListMatch : true } ] ,
45- } ;
42+ const cancerRelevanceOmits = [ 'exp' ] ;
43+ const geneLinkedVariantTypes = [ 'mut' , 'cnv' , 'exp' ] ;
4644
4745const getRapidReportVariants = async ( tableName , variantType , reportId , rapidTable ) => {
4846 let allKbMatches ;
49- if (
50- unknownSignificanceIncludes . includes ( variantType )
51- && ! signatureVariant . includes ( variantType )
52- ) {
53- allKbMatches = await db . models [ tableName ] . scope ( 'extended' ) . findAll ( {
54- order : [ [ 'id' , 'ASC' ] ] ,
55- attributes : {
56- include : [ [ literal ( `'${ variantType } '` ) , 'variantType' ] ] ,
57- } ,
58- where : {
59- reportId,
60- } ,
61- include : [
62- {
63- model : db . models . kbMatches ,
64- attributes : { exclude : KBMATCHEXCLUDE } ,
65- include : [
66- {
67- model : db . models . kbMatchedStatements ,
68- as : 'kbMatchedStatements' ,
69- attributes : {
70- exclude : STATEMENTEXCLUDE ,
71- } ,
72- // where: {
73- // ...therapeuticAssociationFilterStatement,
74- // },
75- through : { attributes : [ 'flags' ] } ,
47+
48+ const query = {
49+ order : [ [ 'id' , 'ASC' ] ] ,
50+ attributes : {
51+ include : [ [ literal ( `'${ variantType } '` ) , 'variantType' ] ] ,
52+ } ,
53+ where : {
54+ reportId,
55+ } ,
56+ include : [
57+ {
58+ model : db . models . kbMatches ,
59+ attributes : { exclude : KBMATCHEXCLUDE } ,
60+ include : [
61+ {
62+ model : db . models . kbMatchedStatements ,
63+ as : 'kbMatchedStatements' ,
64+ attributes : {
65+ exclude : STATEMENTEXCLUDE ,
7666 } ,
77- ] ,
78- } ,
79- {
80- model : db . models . observedVariantAnnotations ,
81- attributes : { exclude : OBSVARANNOTEXCLUDE } ,
82- as : 'observedVariantAnnotation' ,
83- } ,
84- {
85- model : db . models . genes . scope ( 'minimal' ) ,
86- as : 'gene' ,
87- where : unknownSignificanceGeneFilter , // TODO does including this remove results that would otherwise be in allKbMatches
88- } ,
89- ] ,
90- } ) ;
91- } else {
92- allKbMatches = await db . models [ tableName ] . scope ( 'extended' ) . findAll ( {
93- order : [ [ 'id' , 'ASC' ] ] ,
94- attributes : {
95- include : [ [ literal ( `'${ variantType } '` ) , 'variantType' ] ] ,
67+ through : { attributes : [ 'flags' ] } ,
68+ } ,
69+ ] ,
9670 } ,
97- where : {
98- reportId,
71+ {
72+ model : db . models . observedVariantAnnotations ,
73+ attributes : { exclude : OBSVARANNOTEXCLUDE } ,
74+ as : 'observedVariantAnnotation' ,
9975 } ,
100- include : [
101- {
102- model : db . models . kbMatches ,
103- attributes : { exclude : KBMATCHEXCLUDE } ,
104- include : [
105- {
106- model : db . models . kbMatchedStatements ,
107- as : 'kbMatchedStatements' ,
108- attributes : {
109- exclude : STATEMENTEXCLUDE ,
110- } ,
111- through : { attributes : [ 'flags' ] } ,
112- } ,
113- ] ,
114- } ,
115- {
116- model : db . models . observedVariantAnnotations ,
117- attributes : { exclude : OBSVARANNOTEXCLUDE } ,
118- as : 'observedVariantAnnotation' ,
119- } ,
120- ] ,
121- } ) ;
76+ ] ,
77+ } ;
78+ if ( geneLinkedVariantTypes . includes ( variantType ) ) {
79+ const geneSubquery = {
80+ model : db . models . genes . scope ( 'minimal' ) ,
81+ as : 'gene' ,
82+ } ;
83+ query . include . push ( geneSubquery ) ;
84+ }
85+
86+ // if the table is unknownSignificance, only get subset of variant types
87+ if ( rapidTable === 'unknownSignificance' ) {
88+ if ( unknownSignificanceIncludes . includes ( variantType ) ) {
89+ allKbMatches = await db . models [ tableName ] . scope ( 'extended' ) . findAll ( query ) ;
90+ }
91+ } else if ( rapidTable === 'cancerRelevance' ) {
92+ // exclude expression variants from cancer relevance table
93+ if ( ! cancerRelevanceOmits . includes ( variantType ) ) {
94+ allKbMatches = await db . models [ tableName ] . scope ( 'extended' ) . findAll ( query ) ;
95+ }
96+ } else {
97+ allKbMatches = await db . models [ tableName ] . scope ( 'extended' ) . findAll ( query ) ;
98+ }
99+
100+ if ( ! allKbMatches ) {
101+ return [ ] ;
122102 }
123103
124104 // do initial filtering based on contents of annotations - these should override defaults
@@ -159,6 +139,7 @@ const getRapidReportVariants = async (tableName, variantType, reportId, rapidTab
159139 const variantRegexMatch = item . kbVariant . match ( MUTATION_REGEX ) ;
160140 return ! ( variantRegexMatch ) ;
161141 } ) ;
142+
162143 return variant ;
163144 } ) ;
164145
@@ -181,6 +162,7 @@ const getRapidReportVariants = async (tableName, variantType, reportId, rapidTab
181162 kbmatch . kbMatchedStatements = statements ;
182163 return kbmatch ;
183164 } ) ;
165+
184166 return variant ;
185167 } ) ;
186168
@@ -191,12 +173,14 @@ const getRapidReportVariants = async (tableName, variantType, reportId, rapidTab
191173 . filter ( ( item ) => { return item !== null ; } ) ;
192174 return kbmatch . kbMatchedStatements . length > 0 ;
193175 } ) ;
176+
194177 return variant ;
195178 } ) ;
196179
197180 // remove variants which have no matches
198181 therapeuticAssociationResults = therapeuticAssociationResults . filter ( ( variant ) => {
199182 const kbmatches = variant . kbMatches . filter ( ( item ) => { return item !== null ; } ) ;
183+
200184 return kbmatches . length > 0 ;
201185 } ) ;
202186 }
@@ -209,35 +193,37 @@ const getRapidReportVariants = async (tableName, variantType, reportId, rapidTab
209193
210194 let cancerRelevanceResults = [ ] ;
211195 const cancerRelevanceResultsFiltered = [ ] ;
212- if ( ! ( variantType === 'exp' ) ) { // omit expression variants from this table
213- cancerRelevanceResults = JSON . parse ( JSON . stringify ( allKbMatches ) ) ;
196+ cancerRelevanceResults = JSON . parse ( JSON . stringify ( allKbMatches ) ) ;
214197
215- // remove nonmatching kbmatches
216- cancerRelevanceResults = cancerRelevanceResults . map ( ( variant ) => {
217- const kbmatches = variant . kbMatches . filter ( ( item ) => {
218- const msiMatch = ( item . variantType === 'msi' && item . score >= 20 ) ;
219- if ( msiMatch ) {
220- return true ;
221- }
222- const variantRegexMatch = item . kbVariant . match ( MUTATION_REGEX ) ;
223- return ( ! variantRegexMatch ) ;
224- } ) ;
225- variant . kbMatches = kbmatches ;
226- return variant ;
227- } ) ;
198+ // remove msi variants below cutoff
199+ cancerRelevanceResults = cancerRelevanceResults . filter ( ( variant ) => {
200+ if ( variantType === 'msi' ) {
201+ return ( variant . score >= MSI_CUTOFF ) ;
202+ }
203+ return true ;
204+ } ) ;
228205
229- // remove variants which now have no matches
230- cancerRelevanceResults = cancerRelevanceResults . filter ( ( variant ) => {
231- const kbmatches = variant . kbMatches . filter ( ( item ) => { return item !== null ; } ) ;
232- return kbmatches . length > 0 ;
206+ // remove kbmatches that fail the regex
207+ cancerRelevanceResults = cancerRelevanceResults . map ( ( variant ) => {
208+ const kbmatches = variant . kbMatches . filter ( ( item ) => {
209+ const variantRegexMatch = item . kbVariant . match ( MUTATION_REGEX ) ;
210+ return ( ! variantRegexMatch ) ;
233211 } ) ;
212+ variant . kbMatches = kbmatches ;
213+ return variant ;
214+ } ) ;
234215
235- for ( const row of cancerRelevanceResults ) {
236- if ( ! ( therapeuticAssociationResults . find (
237- ( e ) => { return e . ident === row . ident ; } ,
238- ) ) ) {
239- cancerRelevanceResultsFiltered . push ( row ) ;
240- }
216+ // remove variants which now have no matches
217+ cancerRelevanceResults = cancerRelevanceResults . filter ( ( variant ) => {
218+ const kbmatches = variant . kbMatches . filter ( ( item ) => { return item !== null ; } ) ;
219+ return kbmatches . length > 0 ;
220+ } ) ;
221+
222+ for ( const row of cancerRelevanceResults ) {
223+ if ( ! ( therapeuticAssociationResults . find (
224+ ( e ) => { return e . ident === row . ident ; } ,
225+ ) ) ) {
226+ cancerRelevanceResultsFiltered . push ( row ) ;
241227 }
242228 }
243229
@@ -254,9 +240,17 @@ const getRapidReportVariants = async (tableName, variantType, reportId, rapidTab
254240 unknownSignificanceResults = JSON . parse ( JSON . stringify ( allKbMatches ) ) ;
255241 }
256242
257- // refine unknownSignificance results to only include therapeuticAssoc-qualifying matches
243+ // refine unknownSignificance results to only include variants that EITHER:
244+ // a - have a linked gene that is oncogene, cancerGeneList or tumourSuppressor true, OR
245+ // b - therapeuticAssoc-qualifying matches
258246 // (unless they are tagged - add the tagged results back after filtering)
259247 unknownSignificanceResults = unknownSignificanceResults . map ( ( variant ) => {
248+ if (
249+ // this is safe to check because variantType is smallMutation which always has a gene
250+ variant . gene . oncogene || variant . gene . cancerGeneListMatch || variant . gene . tumourSuppressor
251+ ) {
252+ return variant ;
253+ }
260254 variant . kbMatches = variant . kbMatches . map ( ( kbmatch ) => {
261255 const statements = kbmatch . kbMatchedStatements . filter ( ( stmt ) => {
262256 if ( ( stmt . category === 'therapeutic' )
@@ -276,7 +270,7 @@ const getRapidReportVariants = async (tableName, variantType, reportId, rapidTab
276270 return variant ;
277271 } ) ;
278272
279- // remove matches which have no matching statements
273+ // remove matches which have no matching statements...
280274 unknownSignificanceResults = unknownSignificanceResults . map ( ( variant ) => {
281275 variant . kbMatches = variant . kbMatches . filter ( ( kbmatch ) => {
282276 kbmatch . kbMatchedStatements = kbmatch . kbMatchedStatements
@@ -286,6 +280,11 @@ const getRapidReportVariants = async (tableName, variantType, reportId, rapidTab
286280 return variant ;
287281 } ) ;
288282
283+ // remove variants which have no matches
284+ unknownSignificanceResults = unknownSignificanceResults . filter ( ( variant ) => {
285+ return variant . kbMatches . length > 0 ;
286+ } ) ;
287+
289288 // remove variants already included in a different section
290289 for ( const row of unknownSignificanceResults ) {
291290 if ( ! ( therapeuticAssociationResults . find (
0 commit comments