Skip to content

Commit 62d4971

Browse files
authored
Merge pull request #783 from q4wen/databaseLabels
Database labels
2 parents abd7b96 + 7f09f1d commit 62d4971

File tree

3 files changed

+103
-74
lines changed

3 files changed

+103
-74
lines changed

src/client/features/interactions/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class Interactions extends React.Component {
8989
: source.replace(/\//g,' ')
9090
);
9191
Promise.all(geneIds).then(geneIds=>{
92-
ServerAPI.geneQuery({genes:geneIds.join(' '),target: 'NCBIGENE'}).then(result=>{
92+
ServerAPI.geneQuery({genes:geneIds,target: 'NCBIGENE'}).then(result=>{
9393
const ncbiIds=result.geneInfo.map(gene=> gene.convertedAlias);
9494
ServerAPI.getGeneInformation(ncbiIds).then(result=>{
9595
const geneResults=result.result;

src/client/features/search/landing-box.js

Lines changed: 87 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const { ServerAPI } = require('../../services');
66
const databases = require('../../common/config').databases;
77
const Loader = require('react-loader');
88
const _ = require('lodash');
9+
910
//usedDatabases=[['Uniprot lookup name',{configName:,gProfiler:}]]
1011
const usedDatabases=new Map ([
1112
['GeneCards',{configName:'Gene Cards',gProfiler:'HGNCSYMBOL',displayName:'Gene Cards'}],
@@ -14,7 +15,13 @@ const usedDatabases=new Map ([
1415
['Uniprot',{configName:'Uniprot',gProfiler:'Uniprot',displayName:'Uniprot'}]
1516
]);
1617

17-
const linkBuilder= (source,geneQuery)=>{
18+
/**
19+
* Get database link and display name based on gene ids
20+
* @param {string} source Database name
21+
* @param {JSON} geneQuery User input string and matching gene id.
22+
* @return {string: {string: string}} e.g.{MDM2: {Uiprot: Q00978}}
23+
*/
24+
const idFormatter= (source,geneQuery)=>{
1825
let genes={};
1926
const geneArray=geneQuery.geneInfo;
2027
genes.unrecognized=geneQuery.unrecognized;
@@ -28,27 +35,16 @@ const linkBuilder= (source,geneQuery)=>{
2835
return genes;
2936
};
3037

31-
const pcFallback = (unrecognized,genes) => {
32-
return unrecognized.map(entry=>{
33-
if(!genes[entry]){
34-
return ServerAPI.pcQuery('search', {q:entry,type:'entityreference'}).then((search)=>{
35-
const ids = _.compact(search.searchHit.map(hit=>{
36-
hit =_.reverse(hit.uri.split('/'));
37-
return hit[1]==='uniprot' ? hit[0] : false;
38-
}));
39-
const duplicateCheck = _.compact(ids.map(id=>_.findKey(genes,{'Uniprot':id})));
40-
if(!_.isEmpty(ids) && _.isEmpty(duplicateCheck)){
41-
genes[entry]={'Uniprot': ids[0]};
42-
}
43-
});
44-
}
45-
});
46-
};
47-
38+
/**
39+
* Get database link and display name based on gene ids
40+
* @param {{string:string}} ids NCBI id to search, e.g.{GENE CARD:MDM2}
41+
* @return {[{string:string,string,string}]} Array of database containing link and display name, e.g.{link: URI, displayName: MDM2}
42+
*/
4843
const idToLinkConverter = (ids) =>{
4944
const dbSet = databases.filter(databaseValue => ids[databaseValue.database]);
50-
let dbs = _.assign({},
51-
...dbSet.map(database=>({[database.database]:database.url+database.search+ids[database.database].replace(/[^a-zA-Z0-9:]/g)}))
45+
let dbs = _.assign({}, ...dbSet.map(database=>({
46+
[database.database]: database.url+database.search+ids[database.database].replace(/[^a-zA-Z0-9:]/g)
47+
}))
5248
);
5349

5450
let links = [];
@@ -61,6 +57,12 @@ const idToLinkConverter = (ids) =>{
6157
return links;
6258
};
6359

60+
/**
61+
* Get gene information from NCBI
62+
* @param {string:string} ids NCBI id to search, e.g.{4193:MDM2}
63+
* @param {} genes Validated gene id from databse, e.g.{gene:{db1:id,db2:id}}
64+
* @return {json} JSON of gene information.
65+
*/
6466
const getNcbiInfo = (ids,genes) => {
6567
const ncbiIds=_.map(ids,(search,id)=>id);
6668
return ServerAPI.getGeneInformation(ncbiIds).then(result=>{
@@ -81,7 +83,12 @@ const getNcbiInfo = (ids,genes) => {
8183
});
8284
};
8385

84-
const getUniprotInfo= (ids,genes) => {
86+
/**
87+
* Get gene information from Uniprot
88+
* @param {string:string} ids Uniprot accessions to search, e.g.{4193:MDM2}
89+
* @return {json} JSON of gene information.
90+
*/
91+
const getUniprotInfo= (ids) => {
8592
const uniprotIds=_.map(ids,(search,id)=>id);
8693
return ServerAPI.getUniprotnformation(uniprotIds).then(result=>{
8794
return result.map(gene=>{
@@ -92,24 +99,19 @@ const getUniprotInfo= (ids,genes) => {
9299
}
93100
});
94101
const hgncSymbol = links['Gene Cards'];
95-
const duplicateCheck = _.findKey(genes,{'Gene Cards':hgncSymbol});
96-
if(!duplicateCheck || genes[duplicateCheck]['Uniprot']===gene.accession){
97102
links=idToLinkConverter(links);
98-
return {
99-
databaseID:gene.accession,
100-
name:gene.gene[0].name.value,
101-
function: gene.comments && gene.comments[0].type==='FUNCTION' ? gene.comments[0].text[0].value:'',
102-
hgncSymbol:hgncSymbol,
103-
showMore:{full:true,function:false,synonyms:false},
104-
links:links
105-
};
106-
}
107-
else{
108-
return;
109-
}
103+
return {
104+
databaseID:gene.accession,
105+
name:gene.gene[0].name.value,
106+
function: gene.comments && gene.comments[0].type==='FUNCTION' ? gene.comments[0].text[0].value:'',
107+
hgncSymbol:hgncSymbol,
108+
showMore:{full:true,function:false,synonyms:false},
109+
links:links
110+
};
110111
});
111112
});
112113
};
114+
113115
/*Gets info for a landing box
114116
input: 'TP53'
115117
output: [{
@@ -122,37 +124,59 @@ synonyms:"TP53, BCC7, LFS1, P53, TRP53"
122124
}]
123125
*/
124126
const getLandingResult= (query)=> {
125-
const q=query.trim();
127+
let q=query.trim().split(' ');
128+
let ncbiIds={},uniprotIds={},labeledId={};
129+
const genesToSearch = [];
130+
q.forEach ((id)=> {
131+
const splitId=id.split(':');
132+
133+
//Parse the query based on the format
134+
if(/uniprot:\w+$/i.test(id)) {
135+
uniprotIds[splitId[1]]=splitId[1];
136+
} else if(/(ncbi:[0-9]+|hgnc:\w+)$/i.test(id)) {
137+
labeledId[splitId[1]]=splitId[1];
138+
genesToSearch.push(splitId[1]);
139+
} else {
140+
genesToSearch.push(splitId[0]);
141+
}
142+
});
143+
144+
//Get gene IDs from each database
126145
const promises= [];
127146
usedDatabases.forEach((database)=>promises.push(
128-
ServerAPI.geneQuery({genes: q,target: database.gProfiler}).then(result=>linkBuilder(database.configName,result))
147+
ServerAPI.geneQuery({
148+
genes: genesToSearch,
149+
target: database.gProfiler
150+
}).then(result=>idFormatter(database.configName,result))
129151
));
130-
return Promise.all(promises).then(values=>{
131-
let genes=values[0];
132-
_.tail(values).forEach(gene=>_.mergeWith(genes,gene,(objValue, srcValue)=>_.assign(objValue,srcValue)));
152+
153+
return Promise.all(promises).then(databaseResults=>{
154+
let genes={};
155+
databaseResults.forEach(databaseResult=>_.merge(genes,databaseResult)); //Merge the array of result into one json
133156
return genes;
134-
}).then(genes=>{
135-
let ncbiIds={},uniprotIds={};
136-
_.forEach(genes,(gene,search)=>{
137-
if(gene['NCBI Gene']){
138-
ncbiIds[gene['NCBI Gene']]=search;
139-
}
140-
else if(gene['Uniprot']){
141-
uniprotIds[gene['Uniprot']]=search;
142-
}
143-
});
144-
let landingBoxes=[];
145-
if(!_.isEmpty(ncbiIds)){
146-
landingBoxes.push(getNcbiInfo(ncbiIds,genes));
147-
}
148-
if(!_.isEmpty(uniprotIds)){
149-
landingBoxes.push(getUniprotInfo(uniprotIds,genes));
150-
}
151-
return Promise.all(landingBoxes).then(landingBoxes=> {
152-
landingBoxes=_.compact(_.flatten(landingBoxes));
153-
if(landingBoxes.length>1){landingBoxes.forEach(box=>box.showMore.full=false);}
154-
return landingBoxes;
155-
});
157+
}).then(genes=> {
158+
_.forEach(genes,(gene,search)=>{
159+
if(gene['NCBI Gene']){
160+
ncbiIds[gene['NCBI Gene']]=search;
161+
}
162+
else if(gene['Uniprot']){
163+
uniprotIds[gene['Uniprot']]=search;
164+
}
165+
});
166+
let landingBoxes=[];
167+
if(!_.isEmpty(ncbiIds)){
168+
landingBoxes.push(getNcbiInfo(ncbiIds,genes));
169+
}
170+
if(!_.isEmpty(uniprotIds)){
171+
landingBoxes.push(getUniprotInfo(uniprotIds));
172+
}
173+
return Promise.all(landingBoxes).then(landingBoxes=> {
174+
landingBoxes=_.uniqWith(_.flatten(landingBoxes),(arrVal, othVal)=>
175+
_.intersectionWith(_.values(arrVal.links),_.values(othVal.links),_.isEqual).length
176+
);
177+
if(landingBoxes.length>1){landingBoxes.forEach(box=>box.showMore.full=false);}
178+
return landingBoxes;
179+
});
156180
});
157181
};
158182

@@ -243,7 +267,7 @@ const landingBox = (props) => {
243267
h('div.search-landing-section',{key: 'ids'},[hgncSymbol,otherNames]),
244268
h('div.search-landing-section',{key: 'functions'},[functions]),
245269
h('div.search-landing-section',{key: 'links'},[links]),
246-
interactionsLink(box.databaseID,'View Interactions')
270+
interactionsLink(box.hgncSymbol,'View Interactions')
247271
])
248272
];
249273
});

src/client/services/server-api/index.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,24 @@ const ServerAPI = {
2525
},
2626

2727
querySearch(query){
28-
return fetch(`/pc-client/querySearch?${qs.stringify(query)}`, defaultFetchOpts).then(res => res.json());
28+
const queryClone=_.assign({},query);
29+
if(/(uniprot:\w+|ncbi:[0-9]+|hgnc:\w+)$/.test(queryClone.q)){queryClone.q=queryClone.q.split(':')[1];}
30+
return fetch(`/pc-client/querySearch?${qs.stringify(queryClone)}`, defaultFetchOpts).then(res => res.json());
2931
},
3032

3133
geneQuery(query){
32-
query.genes=query.genes.split(' ');
33-
return fetch('/api/validation', {
34-
method:'POST',
35-
headers: {
36-
'Accept': 'application/json',
37-
'Content-Type': 'application/json'
38-
},
39-
body:JSON.stringify(query)
40-
}).then(res => res.json()).then(ids=> _.assign(ids,{unrecognized:_.tail(ids.unrecognized)}));//remove padding
34+
if(query.genes.length>=1){
35+
return fetch('/api/validation', {
36+
method:'POST',
37+
headers: {
38+
'Accept': 'application/json',
39+
'Content-Type': 'application/json'
40+
},
41+
body:JSON.stringify(query)
42+
}).then(res => res.json());
43+
}else{
44+
return Promise.resolve({geneInfo:[],unrecognized:[]});
45+
}
4146
},
4247

4348
getGeneInformation(ids){

0 commit comments

Comments
 (0)