Skip to content

Commit

Permalink
feat: adding api/cadaPrio (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
holtgrewe authored Jan 30, 2024
1 parent 7edc750 commit 3ad1082
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/api/cadaPrio/client.spec.ts
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:
})
})
34 changes: 34 additions & 0 deletions src/api/cadaPrio/client.ts
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)
}
}
135 changes: 135 additions & 0 deletions src/api/cadaPrio/fixture.predictResponse.json
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"
}
]
2 changes: 2 additions & 0 deletions src/api/cadaPrio/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './types'
export * from './client'
57 changes: 57 additions & 0 deletions src/api/cadaPrio/types.ts
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()

0 comments on commit 3ad1082

Please sign in to comment.