-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import fs from 'fs' | ||
import path from 'path' | ||
import { beforeEach, describe, expect, it, vi } from 'vitest' | ||
import createFetchMock from 'vitest-fetch-mock' | ||
|
||
import { CadaPrioClient } from './client' | ||
import { Response } from './types' | ||
|
||
/** Fixture with prediction results. */ | ||
const cadaPrioPredictResultJson = JSON.parse( | ||
fs.readFileSync(path.resolve(__dirname, './fixture.predictResponse.json'), 'utf8') | ||
) | ||
|
||
/** Initialize mock for `fetch()`. */ | ||
const fetchMocker = createFetchMock(vi) | ||
|
||
describe.concurrent('CadaPrioClient', () => { | ||
beforeEach(() => { | ||
fetchMocker.enableMocks() | ||
fetchMocker.resetMocks() | ||
}) | ||
|
||
it('returns the correct result', async () => { | ||
// arrange: | ||
fetchMocker.mockResponseOnce(JSON.stringify(cadaPrioPredictResultJson)) | ||
|
||
// act: | ||
const client = new CadaPrioClient() | ||
const result = await client.predictGeneImpact(['HP:0000001']) | ||
|
||
// assert: | ||
expect(JSON.stringify(result)).toEqual( | ||
JSON.stringify(Response.fromJson(cadaPrioPredictResultJson)) | ||
) | ||
}) | ||
|
||
it('throws in case of fetching problems', async () => { | ||
// arrange: | ||
fetchMocker.mockResponse(() => { | ||
return Promise.reject(new Error('failed to run cada-prio')) | ||
}) | ||
|
||
// act: | ||
const client = new CadaPrioClient() | ||
// (with guard) | ||
await expect(async () => await client.predictGeneImpact(['HP:0000001'])).rejects.toThrow( | ||
'failed to run cada-prio' | ||
) | ||
|
||
// assert: | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Response } from './types' | ||
|
||
/** Default API base URL to use. */ | ||
const API_BASE_URL = '/internal/proxy/cada-prio/' | ||
|
||
/** | ||
* Client for the CADA-Prio API. | ||
*/ | ||
export class CadaPrioClient { | ||
private apiBaseUrl: string | ||
|
||
constructor(apiBaseUrl?: string) { | ||
this.apiBaseUrl = apiBaseUrl ?? API_BASE_URL | ||
} | ||
|
||
/** | ||
* Predict similarity of genes with list of HPO terms. | ||
* | ||
* @param hpoTerms HPO term IDs (e.g. `HP:0000001`) | ||
* @param geneSymbols Gene symbols (e.g. `BRCA1`) | ||
* @returns Promise with response of impact prediction. | ||
* @throws Error if the API returns an error. | ||
*/ | ||
async predictGeneImpact(hpoTerms: string[], geneSymbols?: string[]): Promise<Response> { | ||
const geneSuffix = geneSymbols ? `&gene_symbols=${geneSymbols.join(',')}` : '' | ||
const url = `${this.apiBaseUrl}api/v1/predict?hpo_terms=${hpoTerms.join(',')}${geneSuffix}` | ||
|
||
const response = await fetch(url, { | ||
method: 'GET' | ||
}) | ||
const responseJson = await response.json() | ||
return Response.fromJson(responseJson) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
[ | ||
{ | ||
"rank": 1, | ||
"score": 76.84823608398438, | ||
"gene_symbol": "WNT7A", | ||
"ncbi_gene_id": "7476", | ||
"hgnc_id": "HGNC:12786" | ||
}, | ||
{ | ||
"rank": 2, | ||
"score": 76.46592712402344, | ||
"gene_symbol": "SMARCA2", | ||
"ncbi_gene_id": "6595", | ||
"hgnc_id": "HGNC:11098" | ||
}, | ||
{ | ||
"rank": 3, | ||
"score": 69.20905303955078, | ||
"gene_symbol": "EFL1", | ||
"ncbi_gene_id": "79631", | ||
"hgnc_id": "HGNC:25789" | ||
}, | ||
{ | ||
"rank": 4, | ||
"score": 65.58743286132812, | ||
"gene_symbol": "SRP54", | ||
"ncbi_gene_id": "6729", | ||
"hgnc_id": "HGNC:11301" | ||
}, | ||
{ | ||
"rank": 5, | ||
"score": 63.857845306396484, | ||
"gene_symbol": "HPGD", | ||
"ncbi_gene_id": "3248", | ||
"hgnc_id": "HGNC:5154" | ||
}, | ||
{ | ||
"rank": 6, | ||
"score": 63.840911865234375, | ||
"gene_symbol": "GALNS", | ||
"ncbi_gene_id": "2588", | ||
"hgnc_id": "HGNC:4122" | ||
}, | ||
{ | ||
"rank": 7, | ||
"score": 63.35689926147461, | ||
"gene_symbol": "DNAJC21", | ||
"ncbi_gene_id": "134218", | ||
"hgnc_id": "HGNC:27030" | ||
}, | ||
{ | ||
"rank": 8, | ||
"score": 63.207393646240234, | ||
"gene_symbol": "NOG", | ||
"ncbi_gene_id": "9241", | ||
"hgnc_id": "HGNC:7866" | ||
}, | ||
{ | ||
"rank": 9, | ||
"score": 63.09525680541992, | ||
"gene_symbol": "ESCO2", | ||
"ncbi_gene_id": "157570", | ||
"hgnc_id": "HGNC:27230" | ||
}, | ||
{ | ||
"rank": 10, | ||
"score": 61.24506378173828, | ||
"gene_symbol": "COL11A1", | ||
"ncbi_gene_id": "1301", | ||
"hgnc_id": "HGNC:2186" | ||
}, | ||
{ | ||
"rank": 11, | ||
"score": 60.995365142822266, | ||
"gene_symbol": "PTDSS1", | ||
"ncbi_gene_id": "9791", | ||
"hgnc_id": "HGNC:9587" | ||
}, | ||
{ | ||
"rank": 12, | ||
"score": 60.21630859375, | ||
"gene_symbol": "VAC14", | ||
"ncbi_gene_id": "55697", | ||
"hgnc_id": "HGNC:25507" | ||
}, | ||
{ | ||
"rank": 13, | ||
"score": 59.911136627197266, | ||
"gene_symbol": "TBX3", | ||
"ncbi_gene_id": "6926", | ||
"hgnc_id": "HGNC:11602" | ||
}, | ||
{ | ||
"rank": 14, | ||
"score": 59.312957763671875, | ||
"gene_symbol": "GRIA3", | ||
"ncbi_gene_id": "2892", | ||
"hgnc_id": "HGNC:4573" | ||
}, | ||
{ | ||
"rank": 15, | ||
"score": 59.29935836791992, | ||
"gene_symbol": "RNU4ATAC", | ||
"ncbi_gene_id": "100151683", | ||
"hgnc_id": "HGNC:34016" | ||
}, | ||
{ | ||
"rank": 16, | ||
"score": 58.710994720458984, | ||
"gene_symbol": "GDF5", | ||
"ncbi_gene_id": "8200", | ||
"hgnc_id": "HGNC:4220" | ||
}, | ||
{ | ||
"rank": 17, | ||
"score": 56.57151412963867, | ||
"gene_symbol": "TRAPPC2", | ||
"ncbi_gene_id": "6399", | ||
"hgnc_id": "HGNC:23068" | ||
}, | ||
{ | ||
"rank": 18, | ||
"score": 55.67450714111328, | ||
"gene_symbol": "IHH", | ||
"ncbi_gene_id": "3549", | ||
"hgnc_id": "HGNC:5956" | ||
}, | ||
{ | ||
"rank": 19, | ||
"score": 55.3505859375, | ||
"gene_symbol": "PCNT", | ||
"ncbi_gene_id": "5116", | ||
"hgnc_id": "HGNC:16068" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './types' | ||
export * from './client' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* One entry of the result as returned by the API. | ||
*/ | ||
export interface ResponseEntry$Api { | ||
/** The HPO term. */ | ||
hpo_term: string | ||
/** The gene symbol. */ | ||
gene_symbol: string | ||
/** The predicted impact. */ | ||
impact: string | ||
} | ||
|
||
/** | ||
* One entry of the result. | ||
*/ | ||
export interface ResponseEntry { | ||
/** The HPO term. */ | ||
hpoTerm: string | ||
/** The gene symbol. */ | ||
geneSymbol: string | ||
/** The predicted impact. */ | ||
impact: string | ||
} | ||
|
||
/** Helper class for converting `ResponseEntry$Api` to `ResponseEntry`. */ | ||
class ResponseEntry$Type { | ||
/** Converts `ResponseEntry$Api` to `ResponseEntry`. */ | ||
fromJson(data: ResponseEntry$Api): ResponseEntry { | ||
return { | ||
hpoTerm: data.hpo_term, | ||
geneSymbol: data.gene_symbol, | ||
impact: data.impact | ||
} | ||
} | ||
} | ||
|
||
/** Helper instance for converting `ResponseEntry$Api` to `ResponseEntry`. */ | ||
export const ResponseEntry = new ResponseEntry$Type() | ||
|
||
/** Type for the response of the `predict` endpoint. */ | ||
export interface Response { | ||
/** The result entries. */ | ||
entries: ResponseEntry[] | ||
} | ||
|
||
/** Helper class for converting JSON from API to `Response`. */ | ||
class Response$Type { | ||
/** Converts JSON from API to `Response`. */ | ||
fromJson(data: any[]): Response { | ||
return { | ||
entries: data.map((entry) => ResponseEntry.fromJson(entry)) | ||
} | ||
} | ||
} | ||
|
||
/** Helper instance for converting JSON to `Response`. */ | ||
export const Response = new Response$Type() |