@sjcrh/proteinpaint-server 2.44.0 → 2.46.1
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/dataset/clinvar.hg19.js +53 -52
- package/dataset/clinvar.hg38.js +74 -73
- package/dataset/clinvar.js +164 -47
- package/dataset/termdb.test.js +257 -0
- package/genome/CriGri.js +1859 -27
- package/genome/cgc.js +743 -7
- package/genome/danRer10.js +1108 -46
- package/genome/dm3.js +71 -44
- package/genome/dm6.js +1926 -45
- package/genome/galGal5.js +23522 -46
- package/genome/galGal6.js +512 -46
- package/genome/hg19.js +293 -198
- package/genome/hg38.js +472 -105
- package/genome/hg38.test.js +406 -40
- package/genome/hgvirus.js +45 -20
- package/genome/mm10.js +135 -67
- package/genome/mm9.js +116 -79
- package/genome/rn6.js +1002 -47
- package/package.json +31 -35
- package/routes/_template_.js +30 -0
- package/routes/burden.js +149 -0
- package/routes/dataset.js +266 -0
- package/routes/dsdata.js +127 -0
- package/routes/gdc.maf.js +120 -0
- package/routes/gdc.mafBuild.js +106 -0
- package/routes/gdc.topMutatedGenes.js +465 -0
- package/routes/gene2canonicalisoform.js +41 -0
- package/routes/genelookup.js +52 -0
- package/routes/genomes.js +144 -0
- package/routes/healthcheck.js +30 -0
- package/routes/hicdata.js +98 -0
- package/routes/hicstat.js +55 -0
- package/routes/isoformlst.js +57 -0
- package/routes/ntseq.js +43 -0
- package/routes/pdomain.js +61 -0
- package/routes/snp.js +107 -0
- package/routes/termdb.categories.js +209 -0
- package/routes/termdb.cluster.js +228 -0
- package/routes/termdb.cohort.summary.js +38 -0
- package/routes/termdb.cohorts.js +49 -0
- package/routes/termdb.config.js +202 -0
- package/routes/termdb.getdescrstats.js +102 -0
- package/routes/termdb.getnumericcategories.js +92 -0
- package/routes/termdb.getpercentile.js +108 -0
- package/routes/termdb.getrootterm.js +65 -0
- package/routes/termdb.gettermchildren.js +67 -0
- package/routes/termdb.singleSampleMutation.js +80 -0
- package/routes/termdb.singlecellData.js +46 -0
- package/routes/termdb.singlecellSamples.js +160 -0
- package/routes/termdb.termsbyids.js +59 -0
- package/routes/termdb.topVariablyExpressedGenes.js +171 -0
- package/routes/termdb.violin.js +77 -0
- package/src/app.js +41500 -0
- package/src/serverconfig.js +14 -8
- package/start.js +3 -3
- package/routes/README.md +0 -84
- package/routes/burden.ts +0 -143
- package/routes/gdc.maf.ts +0 -195
- package/routes/gdc.mafBuild.ts +0 -114
- package/routes/gdc.topMutatedGenes.ts +0 -586
- package/routes/genelookup.ts +0 -50
- package/routes/healthcheck.ts +0 -29
- package/routes/hicdata.ts +0 -111
- package/routes/hicstat.ts +0 -55
- package/routes/termdb.categories.ts +0 -245
- package/routes/termdb.cluster.ts +0 -248
- package/routes/termdb.getdescrstats.ts +0 -102
- package/routes/termdb.getnumericcategories.ts +0 -99
- package/routes/termdb.getpercentile.ts +0 -118
- package/routes/termdb.getrootterm.ts +0 -73
- package/routes/termdb.gettermchildren.ts +0 -82
- package/routes/termdb.singleSampleMutation.ts +0 -87
- package/routes/termdb.singlecellData.ts +0 -49
- package/routes/termdb.singlecellSamples.ts +0 -175
- package/routes/termdb.termsbyids.ts +0 -63
- package/routes/termdb.topVariablyExpressedGenes.ts +0 -214
- package/routes/termdb.violin.ts +0 -77
- package/server.js +0 -2
- package/server.js.map +0 -1
- package/shared/common.js +0 -1080
- package/shared/termdb.initbinconfig.js +0 -96
- package/shared/vcf.js +0 -629
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { read_file } from "#src/utils.js";
|
|
4
|
+
import serverconfig from "#src/serverconfig.js";
|
|
5
|
+
import { gdcValidate_query_singleSampleMutation } from "#src/mds3.gdc.js";
|
|
6
|
+
const api = {
|
|
7
|
+
endpoint: "termdb/singleSampleMutation",
|
|
8
|
+
methods: {
|
|
9
|
+
get: {
|
|
10
|
+
init,
|
|
11
|
+
request: {
|
|
12
|
+
typeId: "TermdbSingleSampleMutationRequest"
|
|
13
|
+
},
|
|
14
|
+
response: {
|
|
15
|
+
typeId: "TermdbSingleSampleMutationResponse"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function init({ genomes }) {
|
|
21
|
+
return async (req, res) => {
|
|
22
|
+
const q = req.query;
|
|
23
|
+
let result;
|
|
24
|
+
try {
|
|
25
|
+
const g = genomes[q.genome];
|
|
26
|
+
if (!g)
|
|
27
|
+
throw "invalid genome name";
|
|
28
|
+
const ds = g.datasets[q.dslabel];
|
|
29
|
+
if (!ds)
|
|
30
|
+
throw "invalid dataset name";
|
|
31
|
+
if (!ds.queries?.singleSampleMutation)
|
|
32
|
+
throw "not supported on this dataset";
|
|
33
|
+
result = await ds.queries.singleSampleMutation.get(q);
|
|
34
|
+
} catch (e) {
|
|
35
|
+
if (e.stack)
|
|
36
|
+
console.log(e.stack);
|
|
37
|
+
result = {
|
|
38
|
+
status: e.status || 400,
|
|
39
|
+
error: e.message || e
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
res.send(result);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function validate_query_singleSampleMutation(ds, genome) {
|
|
46
|
+
const _q = ds.queries.singleSampleMutation;
|
|
47
|
+
if (!_q)
|
|
48
|
+
return;
|
|
49
|
+
if (_q.src == "gdcapi") {
|
|
50
|
+
gdcValidate_query_singleSampleMutation(ds, genome);
|
|
51
|
+
} else if (_q.src == "native") {
|
|
52
|
+
_q.get = async (q) => {
|
|
53
|
+
let fileName = q.sample;
|
|
54
|
+
if (ds.cohort?.termdb?.q?.sampleName2id) {
|
|
55
|
+
fileName = ds.cohort.termdb.q.sampleName2id(q.sample);
|
|
56
|
+
if (fileName == void 0) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const file = path.join(serverconfig.tpmasterdir, _q.folder, fileName.toString());
|
|
61
|
+
try {
|
|
62
|
+
await fs.promises.stat(file);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
if (e.code == "EACCES")
|
|
65
|
+
throw "cannot read file, permission denied";
|
|
66
|
+
if (e.code == "ENOENT")
|
|
67
|
+
throw "no data for this sample";
|
|
68
|
+
throw "failed to load data";
|
|
69
|
+
}
|
|
70
|
+
const data = await read_file(file);
|
|
71
|
+
return { mlst: JSON.parse(data) };
|
|
72
|
+
};
|
|
73
|
+
} else {
|
|
74
|
+
throw "unknown singleSampleMutation.src";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
api,
|
|
79
|
+
validate_query_singleSampleMutation
|
|
80
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const api = {
|
|
2
|
+
endpoint: "termdb/singlecellData",
|
|
3
|
+
methods: {
|
|
4
|
+
get: {
|
|
5
|
+
init,
|
|
6
|
+
request: {
|
|
7
|
+
typeId: "TermdbSinglecellDataRequest"
|
|
8
|
+
},
|
|
9
|
+
response: {
|
|
10
|
+
typeId: "TermdbSinglecellDataResponse"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
post: {
|
|
14
|
+
alternativeFor: "get",
|
|
15
|
+
init
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
function init({ genomes }) {
|
|
20
|
+
return async (req, res) => {
|
|
21
|
+
const q = req.query;
|
|
22
|
+
let result;
|
|
23
|
+
try {
|
|
24
|
+
const g = genomes[q.genome];
|
|
25
|
+
if (!g)
|
|
26
|
+
throw "invalid genome name";
|
|
27
|
+
const ds = g.datasets[q.dslabel];
|
|
28
|
+
if (!ds)
|
|
29
|
+
throw "invalid dataset name";
|
|
30
|
+
if (!ds.queries?.singleCell)
|
|
31
|
+
throw "no singlecell data on this dataset";
|
|
32
|
+
result = await ds.queries.singleCell.data.get(q);
|
|
33
|
+
} catch (e) {
|
|
34
|
+
if (e.stack)
|
|
35
|
+
console.log(e);
|
|
36
|
+
result = {
|
|
37
|
+
status: e.status || 400,
|
|
38
|
+
error: e.message || e
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
res.send(result);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
api
|
|
46
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { read_file } from "#src/utils.js";
|
|
4
|
+
import serverconfig from "#src/serverconfig.js";
|
|
5
|
+
import { gdc_validate_query_singleCell_samples, gdc_validate_query_singleCell_data } from "#src/mds3.gdc.js";
|
|
6
|
+
const api = {
|
|
7
|
+
endpoint: "termdb/singlecellSamples",
|
|
8
|
+
methods: {
|
|
9
|
+
get: {
|
|
10
|
+
init,
|
|
11
|
+
request: {
|
|
12
|
+
typeId: "TermdbSinglecellsamplesRequest"
|
|
13
|
+
},
|
|
14
|
+
response: {
|
|
15
|
+
typeId: "TermdbSinglecellsamplesResponse"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
post: {
|
|
19
|
+
alternativeFor: "get",
|
|
20
|
+
init
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function init({ genomes }) {
|
|
25
|
+
return async (req, res) => {
|
|
26
|
+
const q = req.query;
|
|
27
|
+
let result;
|
|
28
|
+
try {
|
|
29
|
+
const g = genomes[q.genome];
|
|
30
|
+
if (!g)
|
|
31
|
+
throw "invalid genome name";
|
|
32
|
+
const ds = g.datasets[q.dslabel];
|
|
33
|
+
if (!ds)
|
|
34
|
+
throw "invalid dataset name";
|
|
35
|
+
if (!ds.queries?.singleCell)
|
|
36
|
+
throw "no singlecell data on this dataset";
|
|
37
|
+
result = await ds.queries.singleCell.samples.get(q);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
if (e.stack)
|
|
40
|
+
console.log(e.stack);
|
|
41
|
+
result = {
|
|
42
|
+
status: e.status || 400,
|
|
43
|
+
error: e.message || e
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
res.send(result);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async function validate_query_singleCell(ds, genome) {
|
|
50
|
+
const q = ds.queries.singleCell;
|
|
51
|
+
if (!q)
|
|
52
|
+
return;
|
|
53
|
+
if (q.samples.src == "gdcapi") {
|
|
54
|
+
gdc_validate_query_singleCell_samples(ds, genome);
|
|
55
|
+
} else if (q.samples.src == "native") {
|
|
56
|
+
getSamplesNative(q.samples, ds);
|
|
57
|
+
} else {
|
|
58
|
+
throw "unknown singleCell.samples.src";
|
|
59
|
+
}
|
|
60
|
+
if (q.data.src == "gdcapi") {
|
|
61
|
+
gdc_validate_query_singleCell_data(ds, genome);
|
|
62
|
+
} else if (q.data.src == "native") {
|
|
63
|
+
getDataNative(q.data, ds);
|
|
64
|
+
} else {
|
|
65
|
+
throw "unknown singleCell.data.src";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function getSamplesNative(S, ds) {
|
|
69
|
+
const isSamples = ds.cohort.termdb.q.getAllValues4term(S.isSampleTerm);
|
|
70
|
+
if (isSamples.size == 0)
|
|
71
|
+
throw "no samples found that are identified by isSampleTerm";
|
|
72
|
+
const samples = [];
|
|
73
|
+
for (const sampleid of isSamples.keys()) {
|
|
74
|
+
if (isSamples.get(sampleid) == "1")
|
|
75
|
+
samples.push({
|
|
76
|
+
sample: ds.cohort.termdb.q.id2sampleName(sampleid),
|
|
77
|
+
// string name for display
|
|
78
|
+
sampleid
|
|
79
|
+
// temporarily kept to assign term value to each sample
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (S.sampleColumns) {
|
|
83
|
+
for (const term of S.sampleColumns) {
|
|
84
|
+
const s2v = ds.cohort.termdb.q.getAllValues4term(term.termid);
|
|
85
|
+
for (const s of samples) {
|
|
86
|
+
if (s2v.has(s.sampleid))
|
|
87
|
+
s[term.termid] = s2v.get(s.sampleid);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (const s of samples)
|
|
92
|
+
delete s.sampleid;
|
|
93
|
+
S.get = () => {
|
|
94
|
+
return { samples };
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function getDataNative(D, ds) {
|
|
98
|
+
const nameSet = /* @__PURE__ */ new Set();
|
|
99
|
+
for (const plot of D.plots) {
|
|
100
|
+
if (nameSet.has(plot.name))
|
|
101
|
+
throw "duplicate plot.name";
|
|
102
|
+
nameSet.add(plot.name);
|
|
103
|
+
}
|
|
104
|
+
const _terms = [];
|
|
105
|
+
for (const tid of D.termIds) {
|
|
106
|
+
const t = ds.cohort.termdb.q.termjsonByOneid(tid);
|
|
107
|
+
if (!t)
|
|
108
|
+
throw "invalid term id from queries.singleCell.data.termIds[]";
|
|
109
|
+
_terms.push(t);
|
|
110
|
+
}
|
|
111
|
+
D.get = async (q) => {
|
|
112
|
+
try {
|
|
113
|
+
const tid2cellvalue = {};
|
|
114
|
+
for (const tid of D.termIds)
|
|
115
|
+
tid2cellvalue[tid] = {};
|
|
116
|
+
const plots = [];
|
|
117
|
+
for (const plot of D.plots) {
|
|
118
|
+
const tsvfile = path.join(serverconfig.tpmasterdir, plot.folder, q.sample + plot.fileSuffix);
|
|
119
|
+
try {
|
|
120
|
+
await fs.promises.stat(tsvfile);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
if (e.code == "ENOENT") {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (e.code == "EACCES")
|
|
126
|
+
throw "cannot read file, permission denied";
|
|
127
|
+
throw "failed to load sc data file";
|
|
128
|
+
}
|
|
129
|
+
const lines = (await read_file(tsvfile)).trim().split("\n");
|
|
130
|
+
const cells = [];
|
|
131
|
+
for (let i = 1; i < lines.length; i++) {
|
|
132
|
+
const l = lines[i].split(" ");
|
|
133
|
+
const cellId = l[0], x = Number(l[plot.coordsColumns.x]), y = Number(l[plot.coordsColumns.y]);
|
|
134
|
+
const category = l[plot.colorColumn?.index] || "";
|
|
135
|
+
if (!cellId)
|
|
136
|
+
throw "cell id missing";
|
|
137
|
+
if (!Number.isFinite(x) || !Number.isFinite(y))
|
|
138
|
+
throw "x/y not number";
|
|
139
|
+
cells.push({ cellId, x, y, category });
|
|
140
|
+
for (const tid of D.termIds) {
|
|
141
|
+
tid2cellvalue[tid][cellId] = l[1];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
plots.push({ name: plot.name, cells, colorBy: plot.colorColumn?.name, colorMap: plot.colorColumn?.colorMap });
|
|
145
|
+
}
|
|
146
|
+
if (plots.length == 0) {
|
|
147
|
+
return { nodata: true };
|
|
148
|
+
}
|
|
149
|
+
return { plots, terms: _terms, tid2cellvalue };
|
|
150
|
+
} catch (e) {
|
|
151
|
+
if (e.stack)
|
|
152
|
+
console.log(e.stack);
|
|
153
|
+
return { error: e.message || e };
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
export {
|
|
158
|
+
api,
|
|
159
|
+
validate_query_singleCell
|
|
160
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { copy_term } from "#src/termdb.js";
|
|
2
|
+
const api = {
|
|
3
|
+
endpoint: "termdb/termsbyids",
|
|
4
|
+
methods: {
|
|
5
|
+
get: {
|
|
6
|
+
init,
|
|
7
|
+
request: {
|
|
8
|
+
typeId: "gettermsbyidsRequest"
|
|
9
|
+
},
|
|
10
|
+
response: {
|
|
11
|
+
typeId: "gettermsbyidsResponse"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
post: {
|
|
15
|
+
alternativeFor: "get",
|
|
16
|
+
init
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function init({ genomes }) {
|
|
21
|
+
return async (req, res) => {
|
|
22
|
+
const q = req.query;
|
|
23
|
+
try {
|
|
24
|
+
const g = genomes[req.query.genome];
|
|
25
|
+
if (!g)
|
|
26
|
+
throw "invalid genome name";
|
|
27
|
+
const ds = g.datasets[req.query.dslabel];
|
|
28
|
+
if (!ds)
|
|
29
|
+
throw "invalid dataset name";
|
|
30
|
+
const tdb = ds.cohort.termdb;
|
|
31
|
+
if (!tdb)
|
|
32
|
+
throw "invalid termdb object";
|
|
33
|
+
await trigger_gettermsbyid(q, res, tdb);
|
|
34
|
+
} catch (e) {
|
|
35
|
+
res.send({ error: e?.message || e });
|
|
36
|
+
if (e instanceof Error && e.stack)
|
|
37
|
+
console.log(e);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function trigger_gettermsbyid(q, res, tdb) {
|
|
42
|
+
const terms = {};
|
|
43
|
+
for (const id of q.ids) {
|
|
44
|
+
const term = tdb.q.termjsonByOneid(id);
|
|
45
|
+
if (term) {
|
|
46
|
+
if (term.type == "categorical" && !term.values && !term.groupsetting?.inuse) {
|
|
47
|
+
term.values = {};
|
|
48
|
+
term.samplecount = {};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
terms[id] = term ? copy_term(term) : void 0;
|
|
52
|
+
}
|
|
53
|
+
res.send({
|
|
54
|
+
terms
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
api
|
|
59
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { gdcGetCasesWithExressionDataFromCohort } from "../src/mds3.gdc.js";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { run_rust } from "@sjcrh/proteinpaint-rust";
|
|
4
|
+
import got from "got";
|
|
5
|
+
import serverconfig from "#src/serverconfig.js";
|
|
6
|
+
import { get_samples } from "#src/termdb.sql.js";
|
|
7
|
+
const api = {
|
|
8
|
+
endpoint: "termdb/topVariablyExpressedGenes",
|
|
9
|
+
methods: {
|
|
10
|
+
all: {
|
|
11
|
+
init,
|
|
12
|
+
request: {
|
|
13
|
+
typeId: "TermdbTopVariablyExpressedGenesRequest"
|
|
14
|
+
},
|
|
15
|
+
response: {
|
|
16
|
+
typeId: "TermdbTopVariablyExpressedGenesResponse"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
function init({ genomes }) {
|
|
22
|
+
return async (req, res) => {
|
|
23
|
+
try {
|
|
24
|
+
const q = req.query;
|
|
25
|
+
const genome = genomes[q.genome];
|
|
26
|
+
if (!genome)
|
|
27
|
+
throw "invalid genome";
|
|
28
|
+
const ds = genome.datasets?.[q.dslabel];
|
|
29
|
+
if (!ds)
|
|
30
|
+
throw "invalid dslabel";
|
|
31
|
+
if (!ds.queries?.topVariablyExpressedGenes)
|
|
32
|
+
throw "not supported on dataset";
|
|
33
|
+
const t = Date.now();
|
|
34
|
+
const genes = await ds.queries.topVariablyExpressedGenes.getGenes(q);
|
|
35
|
+
if (serverconfig.debugmode)
|
|
36
|
+
console.log("topVariablyExpressedGenes", Date.now() - t, "ms");
|
|
37
|
+
res.send({ genes });
|
|
38
|
+
} catch (e) {
|
|
39
|
+
res.send({ status: "error", error: e.message || e });
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function validate_query_TopVariablyExpressedGenes(ds, genome) {
|
|
44
|
+
const q = ds.queries.topVariablyExpressedGenes;
|
|
45
|
+
if (!q)
|
|
46
|
+
return;
|
|
47
|
+
if (q.src == "gdcapi") {
|
|
48
|
+
gdcValidateQuery(ds, genome);
|
|
49
|
+
} else if (q.src == "native") {
|
|
50
|
+
nativeValidateQuery(ds, genome);
|
|
51
|
+
} else {
|
|
52
|
+
throw "unknown topVariablyExpressedGenes.src";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function nativeValidateQuery(ds, genome) {
|
|
56
|
+
const gE = ds.queries.geneExpression;
|
|
57
|
+
if (!gE)
|
|
58
|
+
throw "topVariablyExpressedGenes query given but geneExpression missing";
|
|
59
|
+
if (gE.src != "native")
|
|
60
|
+
throw "topVariablyExpressedGenes is native but geneExpression.src is not native";
|
|
61
|
+
ds.queries.topVariablyExpressedGenes.getGenes = async (q) => {
|
|
62
|
+
const samples = [];
|
|
63
|
+
if (q.filter) {
|
|
64
|
+
const sidlst = await get_samples(q.filter, ds);
|
|
65
|
+
for (const i of sidlst) {
|
|
66
|
+
if (gE.samples.includes(i.id)) {
|
|
67
|
+
const n = ds.cohort.termdb.q.id2sampleName(i.id);
|
|
68
|
+
if (!n)
|
|
69
|
+
throw "sample id cannot convert to string name";
|
|
70
|
+
samples.push(n);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
for (const i of gE.samples) {
|
|
75
|
+
const n = ds.cohort.termdb.q.id2sampleName(i.id);
|
|
76
|
+
if (!n)
|
|
77
|
+
throw "sample id cannot convert to string name";
|
|
78
|
+
samples.push(n);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const genes = await computeGenes4nativeDs(q, ds, gE.file, samples);
|
|
82
|
+
return genes;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function computeGenes4nativeDs(q, ds, matrixFile, samples) {
|
|
86
|
+
const input_json = {
|
|
87
|
+
input_file: matrixFile,
|
|
88
|
+
samples: samples.join(","),
|
|
89
|
+
filter_extreme_values: true,
|
|
90
|
+
num_genes: Number(q.maxGenes),
|
|
91
|
+
param: "var"
|
|
92
|
+
};
|
|
93
|
+
const rust_output = await run_rust("topGeneByExpressionVariance", JSON.stringify(input_json));
|
|
94
|
+
const rust_output_list = rust_output.split("\n");
|
|
95
|
+
let output_json;
|
|
96
|
+
for (const item of rust_output_list) {
|
|
97
|
+
if (item.includes("output_json:")) {
|
|
98
|
+
output_json = JSON.parse(item.replace("output_json:", ""));
|
|
99
|
+
} else {
|
|
100
|
+
console.log(item);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const varGenes = output_json.map((i) => i.gene_symbol);
|
|
104
|
+
return varGenes;
|
|
105
|
+
}
|
|
106
|
+
function gdcValidateQuery(ds, genome) {
|
|
107
|
+
ds.queries.topVariablyExpressedGenes.getGenes = async (q) => {
|
|
108
|
+
if (serverconfig.features.gdcGenes) {
|
|
109
|
+
console.log("!!GDC!! using serverconfig.features.gdcGenes[]");
|
|
110
|
+
return serverconfig.features.gdcGenes;
|
|
111
|
+
}
|
|
112
|
+
if (!ds.__gdc.doneCaching)
|
|
113
|
+
throw "The server has not finished caching the case IDs: try again in ~2 minutes";
|
|
114
|
+
const caseLst = await gdcGetCasesWithExressionDataFromCohort(q, ds);
|
|
115
|
+
if (caseLst.length == 0) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
const { host, headers } = ds.getHostHeaders(q);
|
|
119
|
+
const url = path.join(host.geneExp, "/gene_expression/gene_selection");
|
|
120
|
+
try {
|
|
121
|
+
const response = await got.post(url, {
|
|
122
|
+
headers,
|
|
123
|
+
body: JSON.stringify(getGeneSelectionArg(q, caseLst))
|
|
124
|
+
});
|
|
125
|
+
const re = JSON.parse(response.body);
|
|
126
|
+
const genes = [];
|
|
127
|
+
if (!Array.isArray(re.gene_selection))
|
|
128
|
+
throw "re.gene_selection[] is not array";
|
|
129
|
+
for (const i of re.gene_selection) {
|
|
130
|
+
if (i.gene_id && typeof i.gene_id == "string") {
|
|
131
|
+
const t = genome.genedb.getNameByAlias.get(i.gene_id);
|
|
132
|
+
if (t)
|
|
133
|
+
genes.push(t.name);
|
|
134
|
+
} else if (i.symbol && typeof i.symbol == "string") {
|
|
135
|
+
genes.push(i.symbol);
|
|
136
|
+
} else {
|
|
137
|
+
throw "one of re.gene_selection[] is missing both gene_id and symbol";
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return genes;
|
|
141
|
+
} catch (e) {
|
|
142
|
+
console.log(e.stack || e);
|
|
143
|
+
throw e;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
function getGeneSelectionArg(q, caseLst) {
|
|
147
|
+
return {
|
|
148
|
+
case_ids: caseLst,
|
|
149
|
+
//.slice(0, 20),
|
|
150
|
+
gene_ids: tempGetCGCgenes(genome),
|
|
151
|
+
selection_size: Number(q.maxGenes)
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function tempGetCGCgenes(genome) {
|
|
156
|
+
const lst = [];
|
|
157
|
+
for (const s of genome.geneset[0].lst) {
|
|
158
|
+
const a = genome.genedb.getAliasByName.all(s);
|
|
159
|
+
if (a) {
|
|
160
|
+
for (const b of a) {
|
|
161
|
+
if (b.alias.startsWith("ENSG"))
|
|
162
|
+
lst.push(b.alias);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return lst;
|
|
167
|
+
}
|
|
168
|
+
export {
|
|
169
|
+
api,
|
|
170
|
+
validate_query_TopVariablyExpressedGenes
|
|
171
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { trigger_getViolinPlotData } from "#src/termdb.violin.js";
|
|
2
|
+
const api = {
|
|
3
|
+
endpoint: "termdb/violin",
|
|
4
|
+
methods: {
|
|
5
|
+
get: {
|
|
6
|
+
init,
|
|
7
|
+
request: {
|
|
8
|
+
typeId: "getViolinRequest"
|
|
9
|
+
},
|
|
10
|
+
response: {
|
|
11
|
+
typeId: "getViolinResponse"
|
|
12
|
+
},
|
|
13
|
+
examples: [
|
|
14
|
+
{
|
|
15
|
+
request: {
|
|
16
|
+
body: {
|
|
17
|
+
genome: "hg38-test",
|
|
18
|
+
dslabel: "TermdbTest",
|
|
19
|
+
embedder: "localhost",
|
|
20
|
+
devicePixelRatio: 2.200000047683716,
|
|
21
|
+
maxThickness: 150,
|
|
22
|
+
screenThickness: 1218,
|
|
23
|
+
filter: {
|
|
24
|
+
type: "tvslst",
|
|
25
|
+
in: true,
|
|
26
|
+
join: "",
|
|
27
|
+
lst: [
|
|
28
|
+
{
|
|
29
|
+
tag: "cohortFilter",
|
|
30
|
+
type: "tvs",
|
|
31
|
+
tvs: { term: { id: "subcohort", type: "categorical" }, values: [{ key: "ABC", label: "ABC" }] }
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
svgw: 227.27272234672367,
|
|
36
|
+
orientation: "horizontal",
|
|
37
|
+
datasymbol: "bean",
|
|
38
|
+
radius: 5,
|
|
39
|
+
strokeWidth: 0.2,
|
|
40
|
+
axisHeight: 60,
|
|
41
|
+
rightMargin: 50,
|
|
42
|
+
unit: "abs",
|
|
43
|
+
termid: "agedx"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
response: {
|
|
47
|
+
header: { status: 200 }
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
post: {
|
|
53
|
+
alternativeFor: "get",
|
|
54
|
+
init
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
function init({ genomes }) {
|
|
59
|
+
return async (req, res) => {
|
|
60
|
+
const q = req.query;
|
|
61
|
+
try {
|
|
62
|
+
const g = genomes[req.query.genome];
|
|
63
|
+
const ds = g.datasets[req.query.dslabel];
|
|
64
|
+
if (!g)
|
|
65
|
+
throw "invalid genome name";
|
|
66
|
+
const data = await trigger_getViolinPlotData(req.query, null, ds, g);
|
|
67
|
+
res.send(data);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
res.send({ error: e?.message || e });
|
|
70
|
+
if (e instanceof Error && e.stack)
|
|
71
|
+
console.log(e);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
api
|
|
77
|
+
};
|