diff --git a/pharos_database_transforms/README.md b/pharos_database_transforms/README.md index f4006fa..a6abe0d 100644 --- a/pharos_database_transforms/README.md +++ b/pharos_database_transforms/README.md @@ -33,14 +33,17 @@ Here's what that looks like for our AWS server USER = 'ncats' PWORD = '' ``` -4. Run the pharos specific transformations - * Run these python files at the terminal, they will use credentials from credentials.py to update the database +4. Run the pharos specific transformations + * all of these have been moved to pharos-etl repo, go there to do the knex migrations + The only one here that you might want to do is the lychi one if the drug tables have changed + * ~~Run these python files at the terminal, they will use credentials from credentials.py to update the database~~ - * First + * ~~First~~ * create indices and columns necessary for pharos ``` python executeSQLfile.py tcrd-create-indexes.sql ``` + * Second * Populate lychi_h4 keys for all ligands and drugs * write smiles to files @@ -67,7 +70,7 @@ Here's what that looks like for our AWS server python lychi-set.py ``` - * Later + * ~~Later~~ * create and populate the table that hold the lists of IDG targets ``` python executeSQLfile.py tcrd-create-idg-lists.sql @@ -98,7 +101,7 @@ Here's what that looks like for our AWS server ``` python tcrd-create-generif-pubmed-map.py ``` - * Later still + * ~~Later still~~ * create mapping between data sources and all the targets, diseases, and ligands we have data from there for ``` python tcrd-create-datasource-table.py diff --git a/src/TCRD.js b/src/TCRD.js index fd4d72b..2f7d08e 100644 --- a/src/TCRD.js +++ b/src/TCRD.js @@ -470,6 +470,11 @@ OR b.id = (SELECT protein_id FROM xref where xtype = 'Ensembl' and value = ? lim and b.geneid=?`, [args.geneid])); } + if (args.protein_id) { + return this.db.select(this.db.raw(TARGET_SQL + ` +and b.id=?`, [args.protein_id])); + } + return this.db.select(this.db.raw(TARGET_SQL + ` and a.id = ?`, [args.tcrdid])); } @@ -973,7 +978,7 @@ and b.target_id = ?`, [target.tcrdid])); } let q = this.db.select(this.db.raw(p + ` as name, -avg(a.attr_cdf) as value +avg(a.attr_cdf) as value, group_concat(distinct concat(b.name,'!',b.url) order by b.name separator '|') as sources from hgram_cdf a, gene_attribute_type b, t2tc c where a.protein_id = c.protein_id and c.target_id = ? @@ -1724,7 +1729,8 @@ a.*,b.parent_id from do a, do_parent b where a.doid = b.doid`)); getDTO(args) { let matches = []; if (args.dtoid) { - let n = this.dto[args.dtoid]; + const dtoFormat = args.dtoid.replace('_',':'); + let n = this.dto[dtoFormat]; while (n) { matches.push(n); n = n.parent; @@ -1751,7 +1757,7 @@ and b.target_id = ?`, [target.tcrdid])); getTINXForTarget(target, args) { let q = this.db.select(this.db.raw(` -a.*,b.doid, b.score as novelty, a.id as tinxid +a.*, b.doid, b.score as novelty from tinx_importance a, tinx_disease b, t2tc c`)); let sort = true; @@ -1763,7 +1769,7 @@ match(b.name,b.summary) against(? in boolean mode)`, [t])); sort = false; } } - q = q.andWhere(this.db.raw(`a.disease_id = b.id + q = q.andWhere(this.db.raw(`a.doid = b.doid and a.protein_id = c.protein_id and c.target_id = ?`, [target.tcrdid])); diff --git a/src/__tests__/targetQueries/comprehensive.test.js b/src/__tests__/targetQueries/comprehensive.test.js index a8b6e30..b8021f5 100644 --- a/src/__tests__/targetQueries/comprehensive.test.js +++ b/src/__tests__/targetQueries/comprehensive.test.js @@ -225,8 +225,8 @@ describe('all the queries should be consistent with each other', function () { }); test('Similarity query', () => { - const fullList = new TargetList(tcrd, {top:1000000, filter: {similarity: "(Q6P1J9, GWAS)"}}); - const filteredList = new TargetList(tcrd, {filter: {similarity: "(Q6P1J9, GWAS)", facets: [{facet: "Target Development Level", values: ["Tclin"]}]}}); + const fullList = new TargetList(tcrd, {top:1000000, filter: {similarity: "(DRD2, GWAS)"}}); + const filteredList = new TargetList(tcrd, {filter: {similarity: "(DRD2, GWAS)", facets: [{facet: "Target Development Level", values: ["Tclin"]}]}}); const fullCountQuery = fullList.getCountQuery(); const fullListQuery = fullList.getListQuery(); diff --git a/src/db_credentials.js b/src/db_credentials.js index 37a3541..633c63c 100644 --- a/src/db_credentials.js +++ b/src/db_credentials.js @@ -3,9 +3,9 @@ // const cred = { DBHOST: 'tcrd.ncats.io', - DBNAME: 'tcrd684', - CONFIGDB: 'pharos_config_prod', + DBNAME: 'tcrd6110', USER: 'tcrd', - PWORD: '' + PWORD: '', + CONFIGDB: 'pharos_config_prod', }; module.exports.cred = cred; diff --git a/src/models/DataModelList.ts b/src/models/DataModelList.ts index 4bd677b..b8a1173 100644 --- a/src/models/DataModelList.ts +++ b/src/models/DataModelList.ts @@ -157,7 +157,7 @@ export abstract class DataModelList implements IBuildable { return query; }; - getListQuery() { + getListQuery(innerJoinAll: boolean = false) { let dataFields: FieldInfo[]; if (this.fields && this.fields.length > 0) { dataFields = this.GetDataFields('list'); @@ -172,7 +172,7 @@ export abstract class DataModelList implements IBuildable { const queryDefinition = QueryDefinition.GenerateQueryDefinition(this, dataFields); - const query = queryDefinition.generateBaseQuery(false); + const query = queryDefinition.generateBaseQuery(innerJoinAll); this.addFacetConstraints(query, this.filteringFacets); this.addModelSpecificFiltering(query, true, this.dataFields.map(f => f.table)); diff --git a/src/models/databaseTable.ts b/src/models/databaseTable.ts index 97981a6..76fef87 100644 --- a/src/models/databaseTable.ts +++ b/src/models/databaseTable.ts @@ -77,7 +77,8 @@ export class DatabaseTable { ["protein-target", ["t2tc"]], ["protein-ncats_idg_list_type", ["ncats_idg_list"]], ["protein-ncats_ligands", ["ncats_ligand_activity", "target", "t2tc"]], - ["protein-ncats_ligand_activity", ["target", "t2tc"]] + ["protein-ncats_ligand_activity", ["target", "t2tc"]], + ["protein-drgc_resource", ["target", "t2tc"]] ]); static getRequiredLinks(table1: string, table2: string): string[] | undefined { diff --git a/src/models/disease/diseaseList.ts b/src/models/disease/diseaseList.ts index b0b20f6..4d106b2 100644 --- a/src/models/disease/diseaseList.ts +++ b/src/models/disease/diseaseList.ts @@ -41,7 +41,7 @@ export class DiseaseList extends DataModelList { importance:knex.raw('(tinx_importance.score)') }) .join(doidList.as('idList'), 'idList.did', 'tinx_disease.doid') - .where(knex.raw('tinx_importance.disease_id = tinx_disease.id')) + .where(knex.raw('tinx_importance.doid = tinx_disease.doid')) .andWhere(knex.raw('tinx_importance.protein_id = t2tc.protein_id')) .andWhere(knex.raw('tinx_importance.protein_id = tinx_novelty.protein_id')) .andWhere(knex.raw('t2tc.target_id = target.id')); diff --git a/src/models/queryDefinition.ts b/src/models/queryDefinition.ts index 19f5a99..3b8d4f1 100644 --- a/src/models/queryDefinition.ts +++ b/src/models/queryDefinition.ts @@ -144,7 +144,7 @@ export class QueryDefinition { return dataTable.tableName === this.buildable.rootTable && dataTable.alias === this.buildable.rootTable; } - generateBaseQuery(forFacet: boolean){ + generateBaseQuery(innerJoinAll: boolean){ const buildableObj = this.buildable; let rootTableObject = this.getRootTable(); if (rootTableObject == undefined) { @@ -161,7 +161,7 @@ export class QueryDefinition { return; } let joinFunction = 'leftJoin'; - if(forFacet || this.buildable.tableNeedsInnerJoin(dataTable)){ + if(innerJoinAll || this.buildable.tableNeedsInnerJoin(dataTable)){ joinFunction = 'join'; } let leftTable = rootTableObject; diff --git a/src/models/target/targetDetails.ts b/src/models/target/targetDetails.ts index 376304b..e74a285 100644 --- a/src/models/target/targetDetails.ts +++ b/src/models/target/targetDetails.ts @@ -61,4 +61,17 @@ export class TargetDetails{ .orderBy(['startResidue', 'endResidue']); return query; } + + static LD2JSON(ldObject: any){ + const jsonObject: any = {}; + for (const prop in ldObject) { + if (ldObject[prop]['@value']) { + jsonObject[prop] = ldObject[prop]['@value']; + } + else if (ldObject[prop]['rdfs:label']) { + jsonObject[prop] = ldObject[prop]['rdfs:label']; + } + } + return jsonObject; + } } diff --git a/src/resolvers.js b/src/resolvers.js index 864aa6e..e96083d 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -31,13 +31,13 @@ const resolvers = { const pieces = listKey.split('-'); const reqModel = args.modelName ? args.modelName.toLowerCase() : ''; const reqAssocModel = args.associatedModelName ? args.associatedModelName.toLowerCase() : ''; - if (pieces[1] != 'download'){ // must be download lists + if (pieces[1] != 'download') { // must be download lists return false; } if (pieces[0] != reqModel) { // must match the model return false; } - if (pieces[2] == ''){ // normal fields should apply no matter the associated model + if (pieces[2] == '') { // normal fields should apply no matter the associated model return true; } if (pieces[2] == reqAssocModel) { // otherwise, have to have the right associated model, or be for a single entity @@ -54,7 +54,7 @@ const resolvers = { try { if (args.top) { args.top = Math.min(args.top, 250000); - }else{ + } else { args.top = 250000; } listObj = DataModelListFactory.getListObject(args.model, dataSources.tcrd, args); @@ -278,17 +278,17 @@ const resolvers = { } }; const model = tryUnbatch(); - if(model == 'targets'){ + if (model == 'targets') { return getTargetResult(args, dataSources).then(res => { return {targetResult: res}; }) } - if(model == 'diseases'){ + if (model == 'diseases') { return getDiseaseResult(args, dataSources.tcrd).then(res => { return {diseaseResult: res}; }) } - if(model == 'ligands'){ + if (model == 'ligands') { return getLigandResult(args, dataSources.tcrd).then(res => { return {ligandResult: res}; }) @@ -803,6 +803,54 @@ const resolvers = { }); }, + gwasAnalytics: async function (target, args, {dataSources}) { + const geneFieldMap = new Map([]); // there aren't any that are the same across all associations because they may be from different ensg's + const assocFieldMap = new Map([ + ['TIGA ENSG ID', 'ensgID'], + ['Trait Count for Gene', 'traitCountForGene'], + ['Study Count for Gene', 'studyCountForGene'], + ['TIGA Disease Link', 'ncats_disease_id'], + ['EFO ID', 'efoID'], + ['GWAS Trait', 'trait'], + ['Study Count', 'studyCountForAssoc'], + ['SNP Count', 'snpCount'], + ['Weighted SNP Count', 'wSnpCount'], + ['Gene Count for Trait', 'geneCountForTrait'], + ['Study Count for Trait', 'studyCountForTrait'], + ['Median p-value', 'medianPvalue'], + ['Median Odds Ratio', 'medianOddsRatio'], + ['Beta Count', 'betaCount'], + ['Mean Study N', 'meanStudyN'], + ['RCRAS', 'rcras'], + ['Mean Rank', 'meanRank'], + ['Mean Rank Score', 'meanRankScore'] + ]); + const targetList = new TargetList( + dataSources.tcrd, + { + batch: [target.uniprot], + fields: [...Array.from(geneFieldMap.keys()), ...Array.from(assocFieldMap.keys())], + filter: {order: '!Mean Rank Score'} + }); + return targetList.getListQuery(true).then(rows => { + if (!rows || rows.length === 0) { + return null; + } + const gwasObj = {}; + geneFieldMap.forEach((v, k) => { + gwasObj[v] = rows[0][k]; + }); + gwasObj.associations = []; + rows.forEach(row => { + const assoc = {}; + assocFieldMap.forEach((v, k) => { + assoc[v] = row[k]; + }); + gwasObj.associations.push(assoc); + }); + return gwasObj; + }) + }, goCounts: async function (target, _, {dataSources}) { return dataSources.tcrd.getGOCountsForTarget(target) .then(rows => { @@ -960,6 +1008,19 @@ const resolvers = { return targetDetails.getAllFacetValues().then(results => { return results.map(res => res.value); }); + }, + drgc_resources: async function (target, args, {dataSources}) { + const query = dataSources.tcrd.db('drgc_resource') + .select({resourceType: 'resource_type', detailBlob: 'json'}) + .where('target_id', target.tcrdid); + return query.then(rows => { + return rows.map(row => { + return { + resourceType: row.resourceType, + detailBlob: TargetDetails.LD2JSON(JSON.parse(row.detailBlob)) + }; + }); + }); } }, SimilarityDetails: { @@ -1233,27 +1294,81 @@ const resolvers = { }).catch(function (error) { console.error(error); }); + }, + gwasAnalytics: async function (disease, args, {dataSources}) { + const traitFieldMap = new Map([ + ['EFO ID', 'efoID'], + ['GWAS Trait', 'trait'], + ['Gene Count for Trait', 'geneCount'], + ['Study Count for Trait', 'studyCount'] + ]); + const assocFieldMap = new Map([ + ['TIGA Protein ID', 'protein_id'], + ['TIGA ENSG ID', 'ensgID'], + ['Study Count', 'studyCount'], + ['SNP Count', 'snpCount'], + ['Weighted SNP Count', 'wSnpCount'], + ['Trait Count for Gene', 'traitCountForGene'], + ['Study Count for Gene', 'studyCountForGene'], + ['Median p-value', 'medianPvalue'], + ['Median Odds Ratio', 'medianOddsRatio'], + ['Beta Count', 'betaCount'], + ['Mean Study N', 'meanStudyN'], + ['RCRAS', 'rcras'], + ['Mean Rank', 'meanRank'], + ['Mean Rank Score', 'meanRankScore'] + ]); + const diseaseList = new DiseaseList( + dataSources.tcrd, + { + batch: [disease.name], + fields: [...Array.from(traitFieldMap.keys()), ...Array.from(assocFieldMap.keys())], + filter: {order: '!Mean Rank Score'} + }); + return diseaseList.getListQuery(true).then(rows => { + if (!rows || rows.length === 0) { + return null; + } + const gwasObj = {}; + traitFieldMap.forEach((v, k) => { + gwasObj[v] = rows[0][k]; + }); + gwasObj.associations = []; + rows.forEach(row => { + const assoc = {}; + assocFieldMap.forEach((v, k) => { + assoc[v] = row[k]; + }); + gwasObj.associations.push(assoc); + }); + return gwasObj; + }); } }, - - DiseaseAssociation: { - targetCounts: async function (disease, _, {dataSources}) { // TODO: this really doesn't belong here, it recalculates the same thing for all the associations, I left a stub so that it doesn't break with the client, please delete it, oh great and powerful future developer - return resolvers.Disease.targetCounts(disease, _, {dataSources}) + GwasDiseaseAssociation: { + target: async function (gwasData, args, {dataSources}) { + return dataSources.tcrd.getTarget({protein_id: gwasData.protein_id}) .then(rows => { - return rows; - }) - .catch(function (error) { + return rows[0]; + }).catch(function (error) { console.error(error); }); - }, - targets: async function (disease, args, {dataSources}) { // TODO: this too - return resolvers.Disease.targets(disease, args, {dataSources}) - .then(rows => { - return rows; - }) - .catch(function (error) { - console.error(error); + } + }, + GwasTargetAssociation: { + diseaseName: async function (gwasData, args, {dataSources}) { + if (!!gwasData.ncats_disease_id) { + const query = dataSources.tcrd.db('ncats_disease') + .select({name: 'name'}) + .where('id', gwasData.ncats_disease_id); + return query.then(rows => { + if (rows.length > 0) { + return rows[0].name; + } + return null; }); + } + return null; } }, @@ -1485,17 +1600,16 @@ const resolvers = { let values = new Map(); rows.forEach(r => { - values.set(r.name, r.value); + values.set(r.name, {value: r.value, sources: r.sources.split('|')}); }); let stats = []; map.forEach(r => { let v = values.get(r); - if (v) { - } else { - v = 0; + if (!v) { + v = {value: 0}; } - stats.push({name: r, value: v}); + stats.push({name: r, value: v.value, sources: v.sources}); }); return stats; @@ -1566,7 +1680,7 @@ const resolvers = { synonyms: async function (ligand, args, {dataSources}) { const parser = function (row) { let synonyms = []; - for (let field of ['PubChem', 'Guide to Pharmacology', 'ChEMBL', 'DrugCentral']) { + for (let field of ['unii', 'PubChem', 'Guide to Pharmacology', 'ChEMBL', 'DrugCentral', 'pt']) { if (row[field]) { synonyms.push({name: field, value: row[field]}); } @@ -1576,17 +1690,17 @@ const resolvers = { }; let synonyms = []; - if (!ligand['PubChem'] && !ligand['Guide to Pharmacology'] && !ligand['ChEMBL'] && !ligand['DrugCentral']) { + if (!ligand['PubChem'] && !ligand['Guide to Pharmacology'] && !ligand['ChEMBL'] && !ligand['DrugCentral'] && !ligand['unii'] && !ligand['pt']) { let query = dataSources.tcrd.db('ncats_ligands') - .select(['PubChem', 'Guide to Pharmacology', 'ChEMBL', 'DrugCentral']) + .select(['unii', 'PubChem', 'Guide to Pharmacology', 'ChEMBL', 'DrugCentral', 'pt']) .where('identifier', ligand.ligid); return query.then(rows => { return parser(rows[0]); - }) + }); } return parser(ligand); - } + }, }, LigandActivity: { @@ -1603,9 +1717,10 @@ const resolvers = { TINXDisease: { disease: async function (tinx, _, {dataSources}) { //console.log('~~~~~ tinx: '+tinx.doid); - if (tinx.doid) + if (tinx.doid && dataSources.tcrd.doTree[tinx.doid]) { return dataSources.tcrd.doTree[tinx.doid]; - console.error('No doid in TINX ' + tinx.tinxid); + } + // console.error('No doid in TINX ' + JSON.stringify(tinx)); return null; } } diff --git a/src/schema.graphql b/src/schema.graphql index f94e419..e751aa5 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -42,9 +42,10 @@ type IntProp @cacheControl(maxAge: 604800) { value: Int! } -type FloatProp @cacheControl(maxAge: 604800) { +type HSummaryProp @cacheControl(maxAge: 604800) { name: String! value: Float! + sources: [String] } type TemporalCount @cacheControl(maxAge: 604800) { @@ -191,6 +192,7 @@ type Disease @cacheControl(maxAge: 604800) { parents: [Disease] children: [Disease] tinx: [TINXTarget] + gwasAnalytics: GwasDiseaseAnalytics } type DiseaseID @cacheControl(maxAge: 604800){ @@ -215,9 +217,6 @@ type DiseaseAssociation @cacheControl(maxAge: 604800) { pvalue: Float score: Float source: String - - targetCounts: [IntProp] @deprecated(reason: "use Disease.targetCounts") - targets (skip: Int=0, top: Int=10, filter: IFilter): [Target] @deprecated(reason:"use Disease.targets - each association only has one target anyway") } """Target relationships such as PPI""" @@ -302,7 +301,7 @@ type Harmonizome @cacheControl(maxAge: 604800) { count: Int attrs: [GeneAttribute] """which must be one of 'type', 'group', or 'category'""" - summary (which: String="type"): [FloatProp] + summary (which: String="type"): [HSummaryProp] } type GeneAttribute @cacheControl(maxAge: 604800) { @@ -373,12 +372,11 @@ type DTO @cacheControl(maxAge: 604800) { } type TINXDisease @cacheControl(maxAge: 604800) { - tinxid: Int! """Disease novelty""" novelty: Float """Importance of disease-target combination""" score: Float - disease: DiseaseOntology! + disease: DiseaseOntology } type TINXTargetDetails @cacheControl(maxAge: 604800) { @@ -424,11 +422,17 @@ type SeqAnnotationInfo @cacheControl(maxAge: 604800){ name: String } +type DRGCResource @cacheControl(maxAge: 604800){ + resourceType: String + detailBlob: JSON +} + """Target entity""" type Target @cacheControl(maxAge: 604800){ similarity: SimilarityDetails sequence_variants: SeqVariantInfo sequence_annotations: [SeqAnnotationInfo] + drgc_resources: [DRGCResource] """Internal TCRD ID; should not be used externally!""" tcrdid: Int! @@ -507,6 +511,8 @@ type Target @cacheControl(maxAge: 604800){ gwasCounts: [IntProp] gwas(skip: Int=0, top: Int=10, filter: IFilter): [GWAS] + gwasAnalytics: GwasTargetAnalytics + """GO terms""" goCounts: [IntProp] go(skip: Int=0, top: Int=20, filter: IFilter): [GO] @@ -538,6 +544,56 @@ type Target @cacheControl(maxAge: 604800){ facetValues(facetName: String!, skip: Int=0, top: Int=10): [String] } +type GwasTargetAnalytics @cacheControl(maxAge: 604800) { + associations: [GwasTargetAssociation] +} + +type GwasTargetAssociation @cacheControl(maxAge: 604800) { + ensgID: String + traitCountForGene: Int + studyCountForGene: Int + trait: String + efoID: String + studyCountForAssoc: Int + snpCount: Int + wSnpCount: Float + geneCountForTrait: Int + studyCountForTrait: Int + medianPvalue: Float + medianOddsRatio: Float + betaCount: Int + meanStudyN: Float + rcras: Float + meanRank: Float + meanRankScore: Float + diseaseName: String +} + +type GwasDiseaseAnalytics @cacheControl(maxAge: 604800) { + efoID: String + trait: String + geneCount: Int + studyCount: Int + associations: [GwasDiseaseAssociation] +} + +type GwasDiseaseAssociation @cacheControl(maxAge: 604800) { + target: Target + ensgID: String + studyCount: Int + snpCount: Int + wSnpCount: Float + traitCountForGene: Int + studyCountForGene: Int + medianPvalue: Float + medianOddsRatio: Float + betaCount: Int + meanStudyN: Float + rcras: Float + meanRank: Float + meanRankScore: Float +} + type SimilarTargetResult @cacheControl(maxAge: 604800) { protein_id: Int sym: String diff --git a/tests/test01.graphql b/tests/test01.graphql index b33c2d9..696e3de 100644 --- a/tests/test01.graphql +++ b/tests/test01.graphql @@ -201,14 +201,14 @@ diseases { name associationCount + targets { + sym + tdl + novelty + } associations { disassid did - targets { - sym - tdl - novelty - } } } } @@ -220,6 +220,25 @@ diseases(skip: 40) { name associationCount + targetCounts { + name + value + } + targets( + filter: { + facets: [ + { facet: "tdl", values: ["Tclin"] } + { facet: "fam", values: ["Kinase", "Transporter"] } + ] + } + ) { + sym + uniprot + name + tdl + fam + novelty + } associations { type name @@ -228,25 +247,6 @@ drug pvalue source - targetCounts { - name - value - } - targets( - filter: { - facets: [ - { facet: "tdl", values: ["Tclin"] } - { facet: "fam", values: ["Kinase", "Transporter"] } - ] - } - ) { - sym - uniprot - name - tdl - fam - novelty - } } } patentCounts { diff --git a/tests/test05.graphql b/tests/test05.graphql index d068635..f5a1902 100644 --- a/tests/test05.graphql +++ b/tests/test05.graphql @@ -54,13 +54,13 @@ diseases { name associationCount - associations{ - did targets { sym tdl novelty } + associations{ + did } } } @@ -72,6 +72,25 @@ diseases(skip: 40) { name associationCount + targetCounts { + name + value + } + targets( + filter: { + facets: [ + { facet: "tdl", values: ["Tclin"] } + { facet: "fam", values: ["Kinase", "Transporter"] } + ] + } + ) { + sym + uniprot + name + tdl + fam + novelty + } associations { type did @@ -80,25 +99,7 @@ drug pvalue source - targetCounts { - name - value - } - targets( - filter: { - facets: [ - { facet: "tdl", values: ["Tclin"] } - { facet: "fam", values: ["Kinase", "Transporter"] } - ] - } - ) { - sym - uniprot - name - tdl - fam - novelty - } + } } patentCounts { diff --git a/tests/test12.graphql b/tests/test12.graphql index f3187a7..cac52e2 100644 --- a/tests/test12.graphql +++ b/tests/test12.graphql @@ -27,7 +27,6 @@ } tinxCount tinx(top:50){ - tinxid novelty score disease{