@sjcrh/proteinpaint-server 2.39.0 → 2.39.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/routes/gdc.maf.ts +17 -4
- package/routes/gdc.mafBuild.ts +6 -4
- package/routes/hicdata.ts +2 -2
- package/routes/termdb.cluster.ts +3 -8
- package/routes/termdb.getdescrstats.ts +3 -41
- package/routes/termdb.getrootterm.ts +73 -0
- package/routes/termdb.gettermchildren.ts +82 -0
- package/server.js +1 -1
- package/server.js.map +1 -1
package/package.json
CHANGED
package/routes/gdc.maf.ts
CHANGED
|
@@ -3,15 +3,28 @@ import path from 'path'
|
|
|
3
3
|
import got from 'got'
|
|
4
4
|
import serverconfig from '#src/serverconfig.js'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/*
|
|
7
|
+
this route lists available gdc MAF files based on user's cohort filter
|
|
8
|
+
and return them to client to be shown in a table for selection
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const apihost = process.env.PP_GDC_HOST || 'https://api.gdc.cancer.gov' // to switch to serverconfig export
|
|
12
|
+
|
|
13
|
+
const maxFileNumber = 1000 // determines max number of files to return to client
|
|
14
|
+
// preliminary testing:
|
|
15
|
+
// 36s for 1000 (87Mb)
|
|
16
|
+
// 78s for 2000 (177Mb)
|
|
17
|
+
// if safe to increase to 2000, maybe fast when this runs in gdc env
|
|
18
|
+
|
|
8
19
|
const allowedWorkflowType = 'Aliquot Ensemble Somatic Variant Merging and Masking'
|
|
9
|
-
|
|
20
|
+
|
|
21
|
+
// change to 400 so it won't limit number of files; should keep this setting as a safeguard; also it's fast to check file size (.5s in gdc.mafBuild.ts)
|
|
22
|
+
export const maxTotalSizeCompressed = serverconfig.features.gdcMafMaxFileSize || 400000000 // 400Mb
|
|
10
23
|
|
|
11
24
|
export const api = {
|
|
12
25
|
endpoint: 'gdc/maf',
|
|
13
26
|
methods: {
|
|
14
|
-
|
|
27
|
+
all: {
|
|
15
28
|
init,
|
|
16
29
|
request: {
|
|
17
30
|
typeId: 'GdcMafRequest'
|
package/routes/gdc.mafBuild.ts
CHANGED
|
@@ -5,9 +5,9 @@ import { run_rust_stream } from '@sjcrh/proteinpaint-rust'
|
|
|
5
5
|
import serverconfig from '#src/serverconfig.js'
|
|
6
6
|
import Readable from 'stream'
|
|
7
7
|
import { GdcMafBuildRequest } from '#shared/types/routes/gdc.mafBuild.ts'
|
|
8
|
+
import { maxTotalSizeCompressed } from './gdc.maf.ts'
|
|
8
9
|
|
|
9
10
|
const apihost = process.env.PP_GDC_HOST || 'https://api.gdc.cancer.gov'
|
|
10
|
-
const maxTotalSizeCompressed = serverconfig.features.gdcMafMaxFileSize || 50000000 // 50Mb
|
|
11
11
|
|
|
12
12
|
export const api = {
|
|
13
13
|
endpoint: 'gdc/mafBuild',
|
|
@@ -43,6 +43,7 @@ async function buildMaf(q: GdcMafBuildRequest, res: any) {
|
|
|
43
43
|
const t0 = Date.now()
|
|
44
44
|
|
|
45
45
|
const fileLst2 = (await getFileLstUnderSizeLimit(q.fileIdLst)) as string[]
|
|
46
|
+
|
|
46
47
|
if (serverconfig.debugmode)
|
|
47
48
|
console.log(
|
|
48
49
|
`${fileLst2.length} out of ${q.fileIdLst.length} input MAF files accepted by size limit`,
|
|
@@ -60,11 +61,12 @@ async function buildMaf(q: GdcMafBuildRequest, res: any) {
|
|
|
60
61
|
res.setHeader('Content-Disposition', 'attachment; filename=cohort.maf.gz')
|
|
61
62
|
rustStream.pipe(res)
|
|
62
63
|
|
|
63
|
-
if (serverconfig.debugmode) console.log('rust gdcmaf', Date.now() - t0)
|
|
64
|
-
|
|
65
64
|
rustStream.on('end', () => {
|
|
65
|
+
// report amount of time taken to run rust
|
|
66
|
+
if (serverconfig.debugmode) console.log('rust gdcmaf', Date.now() - t0)
|
|
66
67
|
res.end()
|
|
67
68
|
})
|
|
69
|
+
|
|
68
70
|
rustStream.on('error', err => {
|
|
69
71
|
console.error(err)
|
|
70
72
|
res.statusCode = 500
|
|
@@ -85,7 +87,7 @@ async function getFileLstUnderSizeLimit(lst: string[]) {
|
|
|
85
87
|
op: 'in',
|
|
86
88
|
content: { field: 'file_id', value: lst }
|
|
87
89
|
},
|
|
88
|
-
size:
|
|
90
|
+
size: 10000,
|
|
89
91
|
fields: 'file_size'
|
|
90
92
|
}
|
|
91
93
|
const headers = { 'Content-Type': 'application/json', Accept: 'application/json' }
|
package/routes/hicdata.ts
CHANGED
|
@@ -40,7 +40,7 @@ export const api: any = {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function init(
|
|
43
|
+
function init() {
|
|
44
44
|
return async (req: any, res: any): Promise<void> => {
|
|
45
45
|
try {
|
|
46
46
|
const payload = await handle_hicdata(req.query as HicdataRequest)
|
|
@@ -60,7 +60,7 @@ function handle_hicdata(q: HicdataRequest) {
|
|
|
60
60
|
if (e) reject({ error: 'illegal file name' })
|
|
61
61
|
|
|
62
62
|
const par = [
|
|
63
|
-
|
|
63
|
+
q.matrixType || 'observed',
|
|
64
64
|
q.nmeth || 'NONE',
|
|
65
65
|
file,
|
|
66
66
|
q.pos1,
|
package/routes/termdb.cluster.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { TermdbClusterRequest, TermdbClusterResponse } from '#shared/types/routes/termdb.cluster.ts'
|
|
2
|
-
import fs from 'fs'
|
|
3
2
|
import path from 'path'
|
|
4
3
|
import * as utils from '#src/utils.js'
|
|
5
4
|
import serverconfig from '#src/serverconfig.js'
|
|
@@ -12,7 +11,7 @@ import { dtgeneexpression } from '#shared/common.js'
|
|
|
12
11
|
export const api = {
|
|
13
12
|
endpoint: 'termdb/cluster',
|
|
14
13
|
methods: {
|
|
15
|
-
|
|
14
|
+
all: {
|
|
16
15
|
init,
|
|
17
16
|
request: {
|
|
18
17
|
typeId: 'TermdbClusterRequest'
|
|
@@ -20,10 +19,6 @@ export const api = {
|
|
|
20
19
|
response: {
|
|
21
20
|
typeId: 'TermdbClusterResponse'
|
|
22
21
|
}
|
|
23
|
-
},
|
|
24
|
-
post: {
|
|
25
|
-
alternativeFor: 'get',
|
|
26
|
-
init
|
|
27
22
|
}
|
|
28
23
|
}
|
|
29
24
|
}
|
|
@@ -121,8 +116,8 @@ async function validateNative(q: GeneExpressionQueryNative, ds: any, genome: any
|
|
|
121
116
|
q.get = async (param: TermdbClusterRequest) => {
|
|
122
117
|
const limitSamples = await mayLimitSamples(param, q.samples, ds)
|
|
123
118
|
if (limitSamples?.size == 0) {
|
|
124
|
-
// got 0 sample after filtering, return
|
|
125
|
-
return new Set()
|
|
119
|
+
// got 0 sample after filtering, must still return expected structure with no data
|
|
120
|
+
return { gene2sample2value: new Set(), byTermId: {}, bySampleId: {} }
|
|
126
121
|
}
|
|
127
122
|
|
|
128
123
|
// has at least 1 sample passing filter and with exp data
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getdescrstatsRequest, getdescrstatsResponse } from '#shared/types/routes/termdb.getdescrstats.ts'
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import * as termdbsql from '#src/termdb.sql.js'
|
|
2
|
+
import * as termdbsql from '../src/termdb.sql.js'
|
|
3
|
+
import Summarystats from '../shared/descriptive.stats.js'
|
|
5
4
|
|
|
6
5
|
export const api: any = {
|
|
7
6
|
endpoint: 'termdb/descrstats',
|
|
@@ -104,42 +103,5 @@ async function trigger_getdescrstats(q: any, res: any, ds: any) {
|
|
|
104
103
|
}
|
|
105
104
|
values.push(value)
|
|
106
105
|
}
|
|
107
|
-
|
|
108
|
-
// compute statistics
|
|
109
|
-
// total
|
|
110
|
-
const total = values.length
|
|
111
|
-
|
|
112
|
-
// mean
|
|
113
|
-
const sum = values.reduce((a, b) => a + b, 0)
|
|
114
|
-
const mean = sum / total
|
|
115
|
-
|
|
116
|
-
// percentiles
|
|
117
|
-
const p25 = computePercentile(values, 25)
|
|
118
|
-
const median = computePercentile(values, 50)
|
|
119
|
-
const p75 = computePercentile(values, 75)
|
|
120
|
-
|
|
121
|
-
// standard deviation
|
|
122
|
-
// get sum of squared differences from mean
|
|
123
|
-
const sumSqDiff = values.map(v => (v - mean) ** 2).reduce((a, b) => a + b, 0)
|
|
124
|
-
// get variance
|
|
125
|
-
const variance = sumSqDiff / (values.length - 1)
|
|
126
|
-
// get standard deviation
|
|
127
|
-
const sd = Math.sqrt(variance)
|
|
128
|
-
|
|
129
|
-
// min/max
|
|
130
|
-
const min = Math.min(...values)
|
|
131
|
-
const max = Math.max(...values)
|
|
132
|
-
|
|
133
|
-
res.send({
|
|
134
|
-
values: [
|
|
135
|
-
{ id: 'total', label: 'n', value: total },
|
|
136
|
-
{ id: 'min', label: 'Minimum', value: roundValue(min, 2) },
|
|
137
|
-
{ id: 'p25', label: '1st quartile', value: roundValue(p25, 2) },
|
|
138
|
-
{ id: 'median', label: 'Median', value: roundValue(median, 2) },
|
|
139
|
-
{ id: 'mean', label: 'Mean', value: roundValue(mean, 2) },
|
|
140
|
-
{ id: 'p75', label: '3rd quartile', value: roundValue(p75, 2) },
|
|
141
|
-
{ id: 'max', label: 'Maximum', value: roundValue(max, 2) },
|
|
142
|
-
{ id: 'sd', label: 'Standard deviation', value: roundValue(sd, 2) }
|
|
143
|
-
]
|
|
144
|
-
} as getdescrstatsResponse)
|
|
106
|
+
res.send(Summarystats(values) as getdescrstatsResponse)
|
|
145
107
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { getroottermRequest, getroottermResponse } from '#shared/types/routes/termdb.getrootterm.ts'
|
|
2
|
+
import { get_ds_tdb } from '#src/termdb.js'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const api: any = {
|
|
6
|
+
endpoint: 'termdb/rootterm',
|
|
7
|
+
methods: {
|
|
8
|
+
get: {
|
|
9
|
+
init,
|
|
10
|
+
request: {
|
|
11
|
+
typeId: 'getroottermRequest'
|
|
12
|
+
},
|
|
13
|
+
response: {
|
|
14
|
+
typeId: 'getroottermResponse'
|
|
15
|
+
},
|
|
16
|
+
examples: [
|
|
17
|
+
{
|
|
18
|
+
request: {
|
|
19
|
+
body: {
|
|
20
|
+
genome: 'hg38-test',
|
|
21
|
+
dslabel: 'TermdbTest',
|
|
22
|
+
embedder: 'localhost',
|
|
23
|
+
default_rootterm: 1,
|
|
24
|
+
cohortValues: 'ABC'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
response: {
|
|
28
|
+
header: { status: 200 }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
post: {
|
|
34
|
+
alternativeFor: 'get',
|
|
35
|
+
init
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function init({ genomes }) {
|
|
41
|
+
return async (req: any, res: any): Promise<void> => {
|
|
42
|
+
const q = req.query as getroottermRequest
|
|
43
|
+
const cohortValues = q.cohortValues ? q.cohortValues : ''
|
|
44
|
+
const treeFilter = q.treeFilter ? q.treeFilter : ''
|
|
45
|
+
//res.send({ lst: await tdb.q.getRootTerms(cohortValues, treeFilter) })
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const g = genomes[req.query.genome]
|
|
49
|
+
if (!g) throw 'invalid genome name'
|
|
50
|
+
|
|
51
|
+
const [ds, tdb] = get_ds_tdb(g, q)
|
|
52
|
+
if (!ds) throw 'invalid dataset name'
|
|
53
|
+
if (!tdb) throw 'invalid termdb object'
|
|
54
|
+
|
|
55
|
+
await trigger_rootterm(q, res, tdb) // as getroottermResponse
|
|
56
|
+
} catch (e) {
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
res.send({ error: e?.message || e })
|
|
60
|
+
if (e instanceof Error && e.stack) console.log(e)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function trigger_rootterm(
|
|
66
|
+
q: { cohortValues: any; treeFilter: any },
|
|
67
|
+
res: { send: (arg0: { lst: any }) => void },
|
|
68
|
+
tdb: { q: { getRootTerms: (arg0: any, arg1: any) => any } }
|
|
69
|
+
) {
|
|
70
|
+
const cohortValues = q.cohortValues ? q.cohortValues : ''
|
|
71
|
+
const treeFilter = q.treeFilter ? q.treeFilter : ''
|
|
72
|
+
res.send({ lst: await tdb.q.getRootTerms(cohortValues, treeFilter) } as getroottermResponse)
|
|
73
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { gettermchildrenRequest, gettermchildrenResponse } from '#shared/types/routes/termdb.gettermchildren.ts'
|
|
2
|
+
import { copy_term, get_ds_tdb } from '#src/termdb.js'
|
|
3
|
+
|
|
4
|
+
export const api: any = {
|
|
5
|
+
endpoint: 'termdb/termchildren',
|
|
6
|
+
methods: {
|
|
7
|
+
get: {
|
|
8
|
+
init,
|
|
9
|
+
request: {
|
|
10
|
+
typeId: 'gettermchildrenRequest'
|
|
11
|
+
},
|
|
12
|
+
response: {
|
|
13
|
+
typeId: 'gettermchildrenResponse'
|
|
14
|
+
},
|
|
15
|
+
examples: [
|
|
16
|
+
{
|
|
17
|
+
request: {
|
|
18
|
+
body: {
|
|
19
|
+
genome: 'hg38-test',
|
|
20
|
+
dslabel: 'TermdbTest',
|
|
21
|
+
embedder: 'localhost',
|
|
22
|
+
get_children: 1,
|
|
23
|
+
cohortValues: 'ABC',
|
|
24
|
+
tid: 'GO:0000001'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
response: {
|
|
28
|
+
header: { status: 200 }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
post: {
|
|
34
|
+
alternativeFor: 'get',
|
|
35
|
+
init
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function init({ genomes }) {
|
|
41
|
+
return async (req: any, res: any): Promise<void> => {
|
|
42
|
+
const q = req.query as gettermchildrenRequest
|
|
43
|
+
try {
|
|
44
|
+
const g = genomes[req.query.genome]
|
|
45
|
+
if (!g) throw 'invalid genome name'
|
|
46
|
+
const [ds, tdb] =await get_ds_tdb(g, q)
|
|
47
|
+
if (!ds) throw 'invalid dataset name'
|
|
48
|
+
if (!tdb) throw 'invalid termdb object'
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
await trigger_children(q, res, tdb)
|
|
52
|
+
} catch (e) {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
res.send({ error: e?.message || e })
|
|
56
|
+
if (e instanceof Error && e.stack) console.log(e)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function trigger_children(
|
|
62
|
+
q: {
|
|
63
|
+
genome?: string
|
|
64
|
+
dslabel?: string
|
|
65
|
+
embedder?: string
|
|
66
|
+
get_children?: number
|
|
67
|
+
tid: any
|
|
68
|
+
cohortValues?: any
|
|
69
|
+
treeFilter?: any
|
|
70
|
+
},
|
|
71
|
+
res: { send: (arg0: gettermchildrenResponse) => void },
|
|
72
|
+
tdb: { q: { getTermChildren: (arg0: any, arg1: any, arg2: any) => any } }
|
|
73
|
+
) {
|
|
74
|
+
/* get children terms
|
|
75
|
+
may apply ssid: a premade sample set
|
|
76
|
+
*/
|
|
77
|
+
if (!q.tid) throw 'no parent term id'
|
|
78
|
+
const cohortValues = q.cohortValues ? q.cohortValues : ''
|
|
79
|
+
const treeFilter = q.treeFilter ? q.treeFilter : ''
|
|
80
|
+
const terms = await tdb.q.getTermChildren(q.tid, cohortValues, treeFilter)
|
|
81
|
+
res.send({ lst: terms.map(copy_term) } as gettermchildrenResponse)
|
|
82
|
+
}
|