@sjcrh/proteinpaint-server 2.44.0 → 2.46.0
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 +201 -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 +41498 -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,41 @@
|
|
|
1
|
+
const api = {
|
|
2
|
+
endpoint: "gene2canonicalisoform",
|
|
3
|
+
// should rename to simply 'canonicalIsoform' or 'isoform', gene and type: 'canonical' can be part of payload
|
|
4
|
+
methods: {
|
|
5
|
+
get: {
|
|
6
|
+
init,
|
|
7
|
+
request: {
|
|
8
|
+
typeId: "any"
|
|
9
|
+
},
|
|
10
|
+
response: {
|
|
11
|
+
typeId: "any"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
post: {
|
|
15
|
+
alternativeFor: "get",
|
|
16
|
+
init
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function init({ genomes }) {
|
|
21
|
+
return function(req, res) {
|
|
22
|
+
try {
|
|
23
|
+
if (!req.query.gene)
|
|
24
|
+
throw ".gene missing";
|
|
25
|
+
const genome = genomes[req.query.genome];
|
|
26
|
+
if (!genome)
|
|
27
|
+
throw "unknown genome";
|
|
28
|
+
if (!genome.genedb.get_gene2canonicalisoform)
|
|
29
|
+
throw "gene2canonicalisoform not supported on this genome";
|
|
30
|
+
const data = genome.genedb.get_gene2canonicalisoform.get(req.query.gene);
|
|
31
|
+
res.send(data);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
res.send({ error: e.message || e });
|
|
34
|
+
if (e.stack)
|
|
35
|
+
console.log(e.stack);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
api
|
|
41
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { getResult } from "#src/gene.js";
|
|
2
|
+
function init({ genomes }) {
|
|
3
|
+
return (req, res) => {
|
|
4
|
+
try {
|
|
5
|
+
const q = req.query;
|
|
6
|
+
const g = genomes[req.query.genome];
|
|
7
|
+
if (!g)
|
|
8
|
+
throw "invalid genome name";
|
|
9
|
+
const result = getResult(g, req.query);
|
|
10
|
+
res.send(result);
|
|
11
|
+
} catch (e) {
|
|
12
|
+
res.send({ error: e.message || e });
|
|
13
|
+
if (e.stack)
|
|
14
|
+
console.log(e.stack);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const api = {
|
|
19
|
+
endpoint: "genelookup",
|
|
20
|
+
methods: {
|
|
21
|
+
get: {
|
|
22
|
+
init,
|
|
23
|
+
request: {
|
|
24
|
+
typeId: "GeneLookupRequest"
|
|
25
|
+
//valid: default to type checker
|
|
26
|
+
},
|
|
27
|
+
response: {
|
|
28
|
+
typeId: "GeneLookupResponse"
|
|
29
|
+
// will combine this with type checker
|
|
30
|
+
//valid: (t) => {}
|
|
31
|
+
},
|
|
32
|
+
examples: [
|
|
33
|
+
{
|
|
34
|
+
request: {
|
|
35
|
+
body: { input: "kr", genome: "hg38-test" }
|
|
36
|
+
},
|
|
37
|
+
response: {
|
|
38
|
+
header: { status: 200 },
|
|
39
|
+
body: { hits: ["KRAS"] }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
post: {
|
|
45
|
+
alternativeFor: "get",
|
|
46
|
+
init
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
export {
|
|
51
|
+
api
|
|
52
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import serverconfig from "#src/serverconfig.js";
|
|
3
|
+
import { authApi } from "#src/auth.js";
|
|
4
|
+
import { versionInfo } from "#src/health.ts";
|
|
5
|
+
const api = {
|
|
6
|
+
endpoint: "genomes",
|
|
7
|
+
methods: {
|
|
8
|
+
get: {
|
|
9
|
+
init,
|
|
10
|
+
request: {
|
|
11
|
+
typeId: "any"
|
|
12
|
+
},
|
|
13
|
+
response: {
|
|
14
|
+
typeId: "any"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
post: {
|
|
18
|
+
alternativeFor: "get",
|
|
19
|
+
init
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function init({ genomes }) {
|
|
24
|
+
return async function handle_genomes(req, res) {
|
|
25
|
+
try {
|
|
26
|
+
await fs.promises.stat(serverconfig.tpmasterdir);
|
|
27
|
+
} catch (e) {
|
|
28
|
+
let message = "Error with TP directory (" + e.code + ")";
|
|
29
|
+
const m = serverconfig.maintenance || {};
|
|
30
|
+
if ("start" in m && "stop" in m && m.tpMessage) {
|
|
31
|
+
const start = +new Date(m.start);
|
|
32
|
+
const stop = +new Date(m.stop);
|
|
33
|
+
const currTime = +/* @__PURE__ */ new Date();
|
|
34
|
+
if (start <= currTime && currTime <= stop) {
|
|
35
|
+
message = m.tpMessage;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
res.send({ error: message });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const hash = {};
|
|
42
|
+
if (req.query && req.query.genome) {
|
|
43
|
+
hash[req.query.genome] = clientcopy_genome(req.query.genome, genomes);
|
|
44
|
+
} else {
|
|
45
|
+
for (const genomename in genomes) {
|
|
46
|
+
hash[genomename] = clientcopy_genome(genomename, genomes);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
let hasblat = false;
|
|
50
|
+
for (const n in genomes) {
|
|
51
|
+
if (genomes[n].blat)
|
|
52
|
+
hasblat = true;
|
|
53
|
+
}
|
|
54
|
+
res.send({
|
|
55
|
+
genomes: hash,
|
|
56
|
+
debugmode: serverconfig.debugmode,
|
|
57
|
+
headermessage: serverconfig.headermessage,
|
|
58
|
+
base_zindex: serverconfig.base_zindex,
|
|
59
|
+
codedate: versionInfo.codedate,
|
|
60
|
+
launchdate: versionInfo.launchdate,
|
|
61
|
+
hasblat,
|
|
62
|
+
features: serverconfig.features,
|
|
63
|
+
dsAuth: authApi.getDsAuth(req),
|
|
64
|
+
commonOverrides: serverconfig.commonOverrides,
|
|
65
|
+
targetPortal: serverconfig.targetPortal,
|
|
66
|
+
//sending target portal to the client
|
|
67
|
+
cardsPath: serverconfig.cards?.path
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function clientcopy_genome(genomename, genomes) {
|
|
72
|
+
const g = genomes[genomename];
|
|
73
|
+
const g2 = {
|
|
74
|
+
species: g.species,
|
|
75
|
+
name: genomename,
|
|
76
|
+
hasSNP: g.snp ? true : false,
|
|
77
|
+
hasIdeogram: g.genedb.hasIdeogram,
|
|
78
|
+
fimo_motif: g.fimo_motif ? true : false,
|
|
79
|
+
blat: g.blat ? true : false,
|
|
80
|
+
geneset: g.geneset,
|
|
81
|
+
defaultcoord: g.defaultcoord,
|
|
82
|
+
isdefault: g.isdefault,
|
|
83
|
+
majorchr: g.majorchr,
|
|
84
|
+
majorchrorder: g.majorchrorder,
|
|
85
|
+
minorchr: g.minorchr,
|
|
86
|
+
tracks: g.tracks,
|
|
87
|
+
hicenzymefragment: g.hicenzymefragment,
|
|
88
|
+
datasets: {}
|
|
89
|
+
};
|
|
90
|
+
if (g.termdbs) {
|
|
91
|
+
g2.termdbs = {};
|
|
92
|
+
for (const k in g.termdbs) {
|
|
93
|
+
g2.termdbs[k] = { label: g.termdbs[k].label };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const dsname in g.datasets) {
|
|
97
|
+
const ds = g.datasets[dsname];
|
|
98
|
+
if (ds.isMds3) {
|
|
99
|
+
g2.datasets[ds.label] = {
|
|
100
|
+
isMds3: true,
|
|
101
|
+
noHandleOnClient: ds.noHandleOnClient,
|
|
102
|
+
label: ds.label
|
|
103
|
+
};
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (ds.isMds) {
|
|
107
|
+
g2.datasets[ds.label] = {
|
|
108
|
+
isMds: true,
|
|
109
|
+
mdsIsUninitiated: true,
|
|
110
|
+
noHandleOnClient: ds.noHandleOnClient,
|
|
111
|
+
label: ds.label
|
|
112
|
+
};
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
g2.datasets[ds.label] = {
|
|
116
|
+
isofficial: true,
|
|
117
|
+
legacyDsIsUninitiated: true,
|
|
118
|
+
// so client only gets copy_legacyDataset once
|
|
119
|
+
noHandleOnClient: ds.noHandleOnClient,
|
|
120
|
+
label: ds.label
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (g.hicdomain) {
|
|
124
|
+
g2.hicdomain = { groups: {} };
|
|
125
|
+
for (const s1 in g.hicdomain.groups) {
|
|
126
|
+
const tt = g.hicdomain.groups[s1];
|
|
127
|
+
g2.hicdomain.groups[s1] = {
|
|
128
|
+
name: tt.name,
|
|
129
|
+
reference: tt.reference,
|
|
130
|
+
sets: {}
|
|
131
|
+
};
|
|
132
|
+
for (const s2 in tt.sets) {
|
|
133
|
+
g2.hicdomain.groups[s1].sets[s2] = {
|
|
134
|
+
name: tt.sets[s2].name,
|
|
135
|
+
longname: tt.sets[s2].longname
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return g2;
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
api
|
|
144
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getStat } from "#src/health.ts";
|
|
2
|
+
const api = {
|
|
3
|
+
endpoint: "healthcheck",
|
|
4
|
+
methods: {
|
|
5
|
+
get: {
|
|
6
|
+
init({ genomes }) {
|
|
7
|
+
return async (req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
const health = await getStat(genomes);
|
|
10
|
+
res.send(health);
|
|
11
|
+
} catch (e) {
|
|
12
|
+
res.send({ status: "error", error: e.message || e });
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
request: {
|
|
17
|
+
typeId: null
|
|
18
|
+
//valid: default to type checker
|
|
19
|
+
},
|
|
20
|
+
response: {
|
|
21
|
+
typeId: "HealthCheckResponse"
|
|
22
|
+
// will combine this with type checker
|
|
23
|
+
//valid: (t) => {}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
export {
|
|
29
|
+
api
|
|
30
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { fileurl } from "#src/utils.js";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import readline from "readline";
|
|
4
|
+
import serverconfig from "#src/serverconfig.js";
|
|
5
|
+
const api = {
|
|
6
|
+
endpoint: "hicdata",
|
|
7
|
+
methods: {
|
|
8
|
+
get: {
|
|
9
|
+
init,
|
|
10
|
+
request: {
|
|
11
|
+
typeId: "HicdataRequest"
|
|
12
|
+
},
|
|
13
|
+
response: {
|
|
14
|
+
typeId: "HicdataResponse"
|
|
15
|
+
}
|
|
16
|
+
/*
|
|
17
|
+
examples: [
|
|
18
|
+
{
|
|
19
|
+
request: {
|
|
20
|
+
body: {
|
|
21
|
+
genome: 'hg38-test',
|
|
22
|
+
dslabel: 'TermdbTest',
|
|
23
|
+
embedder: 'localhost',
|
|
24
|
+
gettermbyid: 'subcohort'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
response: {
|
|
28
|
+
header: { status: 200 }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
*/
|
|
33
|
+
},
|
|
34
|
+
post: {
|
|
35
|
+
alternativeFor: "get",
|
|
36
|
+
init
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
function init() {
|
|
41
|
+
return async (req, res) => {
|
|
42
|
+
try {
|
|
43
|
+
const payload = await handle_hicdata(req.query);
|
|
44
|
+
res.send(payload);
|
|
45
|
+
} catch (e) {
|
|
46
|
+
res.send({ error: e?.message || e });
|
|
47
|
+
if (e instanceof Error && e.stack)
|
|
48
|
+
console.log(e);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function handle_hicdata(q) {
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
const [e, file, isurl] = fileurl({ query: q });
|
|
55
|
+
if (e)
|
|
56
|
+
reject({ error: "illegal file name" });
|
|
57
|
+
const matrixType = q.matrixType == "log(oe)" ? "oe" : q.matrixType ? q.matrixType : "observed";
|
|
58
|
+
const par = [matrixType, q.nmeth || "NONE", file, q.pos1, q.pos2, q.isfrag ? "FRAG" : "BP", q.resolution];
|
|
59
|
+
const ps = spawn(serverconfig.hicstraw, par);
|
|
60
|
+
const rl = readline.createInterface({ input: ps.stdout });
|
|
61
|
+
const items = [];
|
|
62
|
+
const erroutput = [];
|
|
63
|
+
let linenot3fields = 0;
|
|
64
|
+
let fieldnotnumerical = 0;
|
|
65
|
+
rl.on("line", (line) => {
|
|
66
|
+
const l = line.split(" ");
|
|
67
|
+
if (l.length != 3) {
|
|
68
|
+
linenot3fields++;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const n1 = Number.parseInt(l[0]);
|
|
72
|
+
const n2 = Number.parseInt(l[1]);
|
|
73
|
+
const v = q.matrixType == "log(oe)" ? Math.log(Number.parseFloat(l[2])) : Number.parseFloat(l[2]);
|
|
74
|
+
if (Number.isNaN(n1) || Number.isNaN(n2) || Number.isNaN(v)) {
|
|
75
|
+
fieldnotnumerical++;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (q.mincutoff != void 0 && v <= q.mincutoff) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
items.push([n1, n2, v]);
|
|
82
|
+
});
|
|
83
|
+
ps.stderr.on("data", (i) => erroutput.push(i));
|
|
84
|
+
ps.on("close", () => {
|
|
85
|
+
const err = erroutput.join("");
|
|
86
|
+
if (err)
|
|
87
|
+
reject({ error: err });
|
|
88
|
+
if (linenot3fields)
|
|
89
|
+
reject({ error: linenot3fields + " lines have other than 3 fields" });
|
|
90
|
+
if (fieldnotnumerical)
|
|
91
|
+
reject({ error: fieldnotnumerical + " lines have non-numerical values in any of the 3 fields" });
|
|
92
|
+
resolve({ items });
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export {
|
|
97
|
+
api
|
|
98
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { fileurl, file_is_readable } from "#src/utils.js";
|
|
2
|
+
import { do_hicstat } from "#src/hicstat.ts";
|
|
3
|
+
const api = {
|
|
4
|
+
endpoint: "hicstat",
|
|
5
|
+
methods: {
|
|
6
|
+
get: {
|
|
7
|
+
init,
|
|
8
|
+
request: {
|
|
9
|
+
typeId: "HicstatRequest"
|
|
10
|
+
},
|
|
11
|
+
response: {
|
|
12
|
+
typeId: "HicstatResponse"
|
|
13
|
+
},
|
|
14
|
+
examples: [
|
|
15
|
+
{
|
|
16
|
+
request: {
|
|
17
|
+
body: {
|
|
18
|
+
genome: "hg19",
|
|
19
|
+
file: "proteinpaint_demo/hg19/hic/hic_demo.hic",
|
|
20
|
+
embedder: "localhost"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
response: {
|
|
24
|
+
header: { status: 200 }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
post: {
|
|
30
|
+
alternativeFor: "get",
|
|
31
|
+
init
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
function init() {
|
|
36
|
+
return async (req, res) => {
|
|
37
|
+
try {
|
|
38
|
+
const [e, file, isurl] = fileurl(req);
|
|
39
|
+
if (e)
|
|
40
|
+
throw "illegal file name";
|
|
41
|
+
if (!isurl) {
|
|
42
|
+
await file_is_readable(file);
|
|
43
|
+
}
|
|
44
|
+
const out = await do_hicstat(file, isurl);
|
|
45
|
+
res.send({ out });
|
|
46
|
+
} catch (e) {
|
|
47
|
+
res.send({ error: e?.message || e });
|
|
48
|
+
if (e instanceof Error && e.stack)
|
|
49
|
+
console.log(e);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
api
|
|
55
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const api = {
|
|
2
|
+
// route endpoint
|
|
3
|
+
// - no need for trailing slash
|
|
4
|
+
// - should be a noun (method is based on HTTP GET, POST, etc)
|
|
5
|
+
// - don't add 'Data' as response is assumed to be data
|
|
6
|
+
endpoint: "isoformlst",
|
|
7
|
+
methods: {
|
|
8
|
+
get: {
|
|
9
|
+
init,
|
|
10
|
+
request: {
|
|
11
|
+
typeId: "any"
|
|
12
|
+
},
|
|
13
|
+
response: {
|
|
14
|
+
typeId: "any"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
post: {
|
|
18
|
+
alternativeFor: "get",
|
|
19
|
+
init
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function init({ genomes }) {
|
|
24
|
+
return function handle_isoformlst(req, res) {
|
|
25
|
+
try {
|
|
26
|
+
const g = genomes[req.query.genome];
|
|
27
|
+
if (!g)
|
|
28
|
+
throw "invalid genome";
|
|
29
|
+
if (!Array.isArray(req.query.lst))
|
|
30
|
+
throw ".lst missing";
|
|
31
|
+
const lst = [];
|
|
32
|
+
for (const isoform of req.query.lst) {
|
|
33
|
+
if (g.genomicNameRegexp.test(isoform))
|
|
34
|
+
continue;
|
|
35
|
+
const tmp = g.genedb.getjsonbyisoform.all(isoform);
|
|
36
|
+
lst.push(
|
|
37
|
+
tmp.map((i) => {
|
|
38
|
+
const j = JSON.parse(i.genemodel);
|
|
39
|
+
if (i.isdefault)
|
|
40
|
+
j.isdefault = true;
|
|
41
|
+
return j;
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
res.send({ lst });
|
|
46
|
+
} catch (e) {
|
|
47
|
+
res.send({ error: e.message || e });
|
|
48
|
+
if (e.stack)
|
|
49
|
+
console.log(e.stack);
|
|
50
|
+
else
|
|
51
|
+
console.trace(e);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
api
|
|
57
|
+
};
|
package/routes/ntseq.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { get_fasta } from "#src/utils.js";
|
|
2
|
+
const api = {
|
|
3
|
+
endpoint: "ntseq",
|
|
4
|
+
methods: {
|
|
5
|
+
get: {
|
|
6
|
+
init,
|
|
7
|
+
request: {
|
|
8
|
+
typeId: "any"
|
|
9
|
+
},
|
|
10
|
+
response: {
|
|
11
|
+
typeId: "any"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
post: {
|
|
15
|
+
alternativeFor: "get",
|
|
16
|
+
init
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function init({ genomes }) {
|
|
21
|
+
return async function handle_ntseq(req, res) {
|
|
22
|
+
try {
|
|
23
|
+
if (!req.query.coord)
|
|
24
|
+
throw "coord missing";
|
|
25
|
+
const g = genomes[req.query.genome];
|
|
26
|
+
if (!g)
|
|
27
|
+
throw "invalid genome";
|
|
28
|
+
if (!g.genomefile)
|
|
29
|
+
throw "no sequence file available";
|
|
30
|
+
const seq = await get_fasta(g, req.query.coord);
|
|
31
|
+
res.send({
|
|
32
|
+
seq: seq.split("\n").slice(1).join("")
|
|
33
|
+
});
|
|
34
|
+
} catch (e) {
|
|
35
|
+
res.send({ error: e.message || e });
|
|
36
|
+
if (e.stack)
|
|
37
|
+
console.log(e.stack);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
api
|
|
43
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const api = {
|
|
2
|
+
// route endpoint
|
|
3
|
+
// - no need for trailing slash
|
|
4
|
+
// - should be a noun (method is based on HTTP GET, POST, etc)
|
|
5
|
+
// - don't add 'Data' as response is assumed to be data
|
|
6
|
+
endpoint: "pdomain",
|
|
7
|
+
methods: {
|
|
8
|
+
get: {
|
|
9
|
+
init,
|
|
10
|
+
request: {
|
|
11
|
+
typeId: "any"
|
|
12
|
+
},
|
|
13
|
+
response: {
|
|
14
|
+
typeId: "any"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
post: {
|
|
18
|
+
alternativeFor: "get",
|
|
19
|
+
init
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function init({ genomes }) {
|
|
24
|
+
return function handle_pdomain(req, res) {
|
|
25
|
+
try {
|
|
26
|
+
const gn = req.query.genome;
|
|
27
|
+
if (!gn)
|
|
28
|
+
throw "no genome";
|
|
29
|
+
const g = genomes[gn];
|
|
30
|
+
if (!g)
|
|
31
|
+
throw "invalid genome " + gn;
|
|
32
|
+
if (!g.proteindomain) {
|
|
33
|
+
return res.send({ lst: [] });
|
|
34
|
+
}
|
|
35
|
+
if (!Array.isArray(req.query.isoforms))
|
|
36
|
+
throw "isoforms[] missing";
|
|
37
|
+
const lst = [];
|
|
38
|
+
for (const isoform of req.query.isoforms) {
|
|
39
|
+
if (g.genomicNameRegexp.test(isoform))
|
|
40
|
+
continue;
|
|
41
|
+
const tmp = g.proteindomain.getbyisoform.all(isoform);
|
|
42
|
+
lst.push({
|
|
43
|
+
name: isoform,
|
|
44
|
+
pdomains: tmp.map((i) => {
|
|
45
|
+
const j = JSON.parse(i.data);
|
|
46
|
+
j.refseq = isoform;
|
|
47
|
+
return j;
|
|
48
|
+
})
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
res.send({ lst });
|
|
52
|
+
} catch (e) {
|
|
53
|
+
res.send({ error: e.message || e });
|
|
54
|
+
if (e.stack)
|
|
55
|
+
console.log(e.stack);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
api
|
|
61
|
+
};
|
package/routes/snp.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as utils from "#src/utils.js";
|
|
2
|
+
const api = {
|
|
3
|
+
// route endpoint
|
|
4
|
+
// - no need for trailing slash
|
|
5
|
+
// - should be a noun (method is based on HTTP GET, POST, etc)
|
|
6
|
+
// - don't add 'Data' as response is assumed to be data
|
|
7
|
+
endpoint: "snp",
|
|
8
|
+
methods: {
|
|
9
|
+
get: {
|
|
10
|
+
init,
|
|
11
|
+
request: {
|
|
12
|
+
typeId: "any"
|
|
13
|
+
},
|
|
14
|
+
response: {
|
|
15
|
+
typeId: "any"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
post: {
|
|
19
|
+
alternativeFor: "get",
|
|
20
|
+
init
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function init({ genomes }) {
|
|
25
|
+
return async function handle_snp(req, res) {
|
|
26
|
+
try {
|
|
27
|
+
const n = req.query.genome;
|
|
28
|
+
if (!n)
|
|
29
|
+
throw "no genome";
|
|
30
|
+
res.send({ results: await searchSNP(req.query, genomes[n]) });
|
|
31
|
+
} catch (e) {
|
|
32
|
+
if (e.stack)
|
|
33
|
+
console.log(e.stack);
|
|
34
|
+
return res.send({ error: e.message || e });
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function searchSNP(q, genome) {
|
|
39
|
+
if (!genome)
|
|
40
|
+
throw "invalid genome";
|
|
41
|
+
if (!genome.snp)
|
|
42
|
+
throw "snp is not configured for this genome";
|
|
43
|
+
const hits = [];
|
|
44
|
+
if (q.byCoord) {
|
|
45
|
+
if (genome.genomicNameRegexp.test(q.chr))
|
|
46
|
+
throw "invalid chr name";
|
|
47
|
+
if (!Array.isArray(q.ranges))
|
|
48
|
+
throw "ranges not an array";
|
|
49
|
+
for (const r of q.ranges) {
|
|
50
|
+
if (!Number.isInteger(r.start) || !Number.isInteger(r.stop) || r.start < 0 || r.stop < r.start)
|
|
51
|
+
throw "invalid start/stop";
|
|
52
|
+
if (r.stop - r.start >= 100) {
|
|
53
|
+
throw "range too big";
|
|
54
|
+
}
|
|
55
|
+
const snps = await utils.query_bigbed_by_coord(genome.snp.bigbedfile, q.chr, r.start, r.stop);
|
|
56
|
+
for (const snp of snps) {
|
|
57
|
+
const hit = snp2hit(snp);
|
|
58
|
+
if (q.alleleLst) {
|
|
59
|
+
let missing = false;
|
|
60
|
+
for (const i of q.alleleLst) {
|
|
61
|
+
if (i && !hit.alleles.includes(i)) {
|
|
62
|
+
missing = true;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (missing)
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
hits.push(hit);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} else if (q.byName) {
|
|
73
|
+
if (!Array.isArray(q.lst))
|
|
74
|
+
throw ".lst[] missing";
|
|
75
|
+
for (const n of q.lst) {
|
|
76
|
+
if (genome.genomicNameRegexp.test(n))
|
|
77
|
+
continue;
|
|
78
|
+
const snps = await utils.query_bigbed_by_name(genome.snp.bigbedfile, n);
|
|
79
|
+
for (const snp of snps) {
|
|
80
|
+
const hit = snp2hit(snp);
|
|
81
|
+
hits.push(hit);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
throw "unknown query method";
|
|
86
|
+
}
|
|
87
|
+
return hits;
|
|
88
|
+
}
|
|
89
|
+
function snp2hit(snp) {
|
|
90
|
+
const fields = snp.split(" ");
|
|
91
|
+
const ref = fields[4];
|
|
92
|
+
const alts = fields[6].split(",").filter(Boolean);
|
|
93
|
+
const observed = ref + "/" + alts.join("/");
|
|
94
|
+
const hit = {
|
|
95
|
+
chrom: fields[0],
|
|
96
|
+
chromStart: Number(fields[1]),
|
|
97
|
+
chromEnd: Number(fields[2]),
|
|
98
|
+
name: fields[3],
|
|
99
|
+
observed,
|
|
100
|
+
alleles: [ref, ...alts]
|
|
101
|
+
};
|
|
102
|
+
return hit;
|
|
103
|
+
}
|
|
104
|
+
export {
|
|
105
|
+
api,
|
|
106
|
+
searchSNP
|
|
107
|
+
};
|