@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.
Files changed (82) hide show
  1. package/dataset/clinvar.hg19.js +53 -52
  2. package/dataset/clinvar.hg38.js +74 -73
  3. package/dataset/clinvar.js +164 -47
  4. package/dataset/termdb.test.js +257 -0
  5. package/genome/CriGri.js +1859 -27
  6. package/genome/cgc.js +743 -7
  7. package/genome/danRer10.js +1108 -46
  8. package/genome/dm3.js +71 -44
  9. package/genome/dm6.js +1926 -45
  10. package/genome/galGal5.js +23522 -46
  11. package/genome/galGal6.js +512 -46
  12. package/genome/hg19.js +293 -198
  13. package/genome/hg38.js +472 -105
  14. package/genome/hg38.test.js +406 -40
  15. package/genome/hgvirus.js +45 -20
  16. package/genome/mm10.js +135 -67
  17. package/genome/mm9.js +116 -79
  18. package/genome/rn6.js +1002 -47
  19. package/package.json +31 -35
  20. package/routes/_template_.js +30 -0
  21. package/routes/burden.js +149 -0
  22. package/routes/dataset.js +266 -0
  23. package/routes/dsdata.js +127 -0
  24. package/routes/gdc.maf.js +120 -0
  25. package/routes/gdc.mafBuild.js +106 -0
  26. package/routes/gdc.topMutatedGenes.js +465 -0
  27. package/routes/gene2canonicalisoform.js +41 -0
  28. package/routes/genelookup.js +52 -0
  29. package/routes/genomes.js +144 -0
  30. package/routes/healthcheck.js +30 -0
  31. package/routes/hicdata.js +98 -0
  32. package/routes/hicstat.js +55 -0
  33. package/routes/isoformlst.js +57 -0
  34. package/routes/ntseq.js +43 -0
  35. package/routes/pdomain.js +61 -0
  36. package/routes/snp.js +107 -0
  37. package/routes/termdb.categories.js +209 -0
  38. package/routes/termdb.cluster.js +228 -0
  39. package/routes/termdb.cohort.summary.js +38 -0
  40. package/routes/termdb.cohorts.js +49 -0
  41. package/routes/termdb.config.js +202 -0
  42. package/routes/termdb.getdescrstats.js +102 -0
  43. package/routes/termdb.getnumericcategories.js +92 -0
  44. package/routes/termdb.getpercentile.js +108 -0
  45. package/routes/termdb.getrootterm.js +65 -0
  46. package/routes/termdb.gettermchildren.js +67 -0
  47. package/routes/termdb.singleSampleMutation.js +80 -0
  48. package/routes/termdb.singlecellData.js +46 -0
  49. package/routes/termdb.singlecellSamples.js +160 -0
  50. package/routes/termdb.termsbyids.js +59 -0
  51. package/routes/termdb.topVariablyExpressedGenes.js +171 -0
  52. package/routes/termdb.violin.js +77 -0
  53. package/src/app.js +41500 -0
  54. package/src/serverconfig.js +14 -8
  55. package/start.js +3 -3
  56. package/routes/README.md +0 -84
  57. package/routes/burden.ts +0 -143
  58. package/routes/gdc.maf.ts +0 -195
  59. package/routes/gdc.mafBuild.ts +0 -114
  60. package/routes/gdc.topMutatedGenes.ts +0 -586
  61. package/routes/genelookup.ts +0 -50
  62. package/routes/healthcheck.ts +0 -29
  63. package/routes/hicdata.ts +0 -111
  64. package/routes/hicstat.ts +0 -55
  65. package/routes/termdb.categories.ts +0 -245
  66. package/routes/termdb.cluster.ts +0 -248
  67. package/routes/termdb.getdescrstats.ts +0 -102
  68. package/routes/termdb.getnumericcategories.ts +0 -99
  69. package/routes/termdb.getpercentile.ts +0 -118
  70. package/routes/termdb.getrootterm.ts +0 -73
  71. package/routes/termdb.gettermchildren.ts +0 -82
  72. package/routes/termdb.singleSampleMutation.ts +0 -87
  73. package/routes/termdb.singlecellData.ts +0 -49
  74. package/routes/termdb.singlecellSamples.ts +0 -175
  75. package/routes/termdb.termsbyids.ts +0 -63
  76. package/routes/termdb.topVariablyExpressedGenes.ts +0 -214
  77. package/routes/termdb.violin.ts +0 -77
  78. package/server.js +0 -2
  79. package/server.js.map +0 -1
  80. package/shared/common.js +0 -1080
  81. package/shared/termdb.initbinconfig.js +0 -96
  82. package/shared/vcf.js +0 -629
package/package.json CHANGED
@@ -1,34 +1,38 @@
1
1
  {
2
2
  "name": "@sjcrh/proteinpaint-server",
3
- "version": "2.44.0",
3
+ "version": "2.46.1",
4
+ "type": "module",
4
5
  "description": "a genomics visualization tool for exploring a cohort's genotype and phenotype data",
5
- "main": "server.js",
6
+ "main": "src/app.js",
7
+ "module": "src/app.js",
6
8
  "bin": "start.js",
7
9
  "imports": {
8
- "#shared/*": "./shared/*",
10
+ "#types": "./shared/types/index.ts",
9
11
  "#shared/types/*": "./shared/types/*",
12
+ "#shared/*": "./shared/*",
10
13
  "#src/*": "./src/*",
11
14
  "#routes/*": "./routes/*"
12
15
  },
13
16
  "scripts": {
14
- "prepare": "ts-patch install",
15
- "dev": "webpack --env NODE_ENV=development --watch --color",
16
- "start": "tsc --esModuleInterop genome/*.ts dataset/*.ts && nodemon --enable-source-maps server.js --watch ./server*.js* --watch dataset/*.ts --watch genome/*.ts",
17
+ "dev": "npm run start",
18
+ "prestart": "tsx emitImports.js dev > server.js",
19
+ "start": "tsx watch src/app.ts",
20
+ "test:unit": "tsx emitImports.js unit > serverTests.js && tsx serverTests.js && rm -rf ./cache",
21
+ "getconf": "../build/getConfigProp.js",
22
+ "doc": "../augen/build.sh routes shared/types/routes shared/checkers ../public/docs/server",
23
+ "mjs": "esbuild \"$DIR/*.ts\" --platform=node --outdir=\"$DIR\" --format=esm",
24
+ "cjs": "esbuild \"$DIR/*.ts\" --platform=node --outdir=\"$DIR\" --format=cjs",
25
+ "build": "./build.sh",
26
+ "prepack": "npm run build",
27
+ "postpack": "./dedupjs.sh",
28
+ "dedup": "./dedupjs.sh",
29
+ "//todo": "refactor or deprecate the scripts below",
17
30
  "pretest": "tsc --esModuleInterop genome/*.ts dataset/*.ts && ./test/pretest.js",
18
- "test": "webpack --env NODE_ENV=test exportsFilename=all-test-context.js && node --enable-source-maps test/serverTests.js",
19
- "precheckers": "tsc --esModuleInterop genome/*.ts dataset/*.ts",
20
- "checkers": "webpack --config=./test/webpack.config.js && node test/emitPrepFiles.bundle.js && typia generate --input shared/checkers-raw --output shared/checkers",
31
+ "prepare": "ts-patch install",
21
32
  "pretest:type": "npm run checkers",
22
- "test:type": "webpack --env NODE_ENV=test exportsFilename=type-test-context.js && node --enable-source-maps test/serverTests.js",
23
- "pretest:unit": "npm run precheckers",
24
- "test:unit": "webpack --env NODE_ENV=test exportsFilename=unit-test-context.js && node --enable-source-maps test/serverTests.js",
25
33
  "pretest:integration": "tsc --esModuleInterop genome/*.ts dataset/*.ts",
26
34
  "test:integration": "echo 'TODO: server integration tests'",
27
- "prepack": "tsc --esModuleInterop genome/*.ts dataset/*.ts && webpack --env NODE_ENV=production",
28
- "test:tsc": "tsc --esModuleInterop --noEmit --allowImportingTsExtensions ./shared/types/test/*.type.spec.ts",
29
- "response": "nodemon modules/test/test.server.js --watch src",
30
- "getconf": "../build/getConfigProp.js",
31
- "doc": "../augen/build.sh routes shared/types/routes shared/checkers ../public/docs/server"
35
+ "test:tsc": "tsc --esModuleInterop --noEmit --allowImportingTsExtensions ./shared/types/test/*.type.spec.ts"
32
36
  },
33
37
  "author": "",
34
38
  "license": "SEE LICENSE IN ./LICENSE",
@@ -39,8 +43,11 @@
39
43
  "@babel/preset-env": "^7.9.6",
40
44
  "@babel/preset-typescript": "^7.21.4",
41
45
  "@babel/register": "^7.14.5",
46
+ "@types/node": "^20.11.24",
42
47
  "@typescript-eslint/eslint-plugin": "^5.60.0",
43
48
  "babel-loader": "^8.2.2",
49
+ "esbuild": "^0.19.12",
50
+ "glob": "^7.2.3",
44
51
  "node-watch": "^0.7.1",
45
52
  "nodemon": "^2.0.19",
46
53
  "prettier": "^2.8.8",
@@ -50,14 +57,10 @@
50
57
  "tsx": "^4.7.1",
51
58
  "typedoc": "^0.24.8",
52
59
  "typescript": "^5.0.3",
53
- "typia": "^4.1.14",
54
- "webpack": "^5.76.0",
55
- "webpack-cli": "^4.9.2",
56
- "webpack-node-externals": "^3.0.0",
57
- "webpack-notifier": "^1.15.0"
60
+ "typia": "^4.1.14"
58
61
  },
59
62
  "dependencies": {
60
- "@sjcrh/augen": "2.43.3-0",
63
+ "@sjcrh/augen": "2.46.0",
61
64
  "@sjcrh/proteinpaint-rust": "2.44.0",
62
65
  "better-sqlite3": "^9.4.1",
63
66
  "body-parser": "^1.15.2",
@@ -68,7 +71,7 @@
68
71
  "deep-object-diff": "^1.1.0",
69
72
  "express": "^4.17.1",
70
73
  "express-basic-auth": "^1.1.5",
71
- "got": "^11.5.1",
74
+ "got": "^14.2.0",
72
75
  "image-size": "^0.5.5",
73
76
  "jsonwebtoken": "^9.0.0",
74
77
  "jstat": "^1.9.3",
@@ -88,24 +91,17 @@
88
91
  },
89
92
  "files": [
90
93
  "bin.js",
91
- "dataset/clinvar*.js",
92
- "dataset/gdc*.js",
94
+ "dataset/*.js",
93
95
  "genome/*.js",
96
+ "routes/*.js",
97
+ "start.js",
98
+ "src/app.js",
94
99
  "src/serverconfig.js",
95
100
  "src/lines2R.js",
96
101
  "src/mds3.gdc.filter.js",
97
102
  "src/checkReadingFrame.js",
98
103
  "src/bedj.parseBed.js",
99
- "routes/*",
100
- "cards/*",
101
- "server.js*",
102
- "start.js",
103
- "shared/common.js",
104
- "shared/termdb.initbinconfig.js",
105
- "shared/vcf.js",
106
104
  "utils/*.R",
107
- "utils/rust/*.*",
108
- "utils/rust/src",
109
105
  "LICENSE/*"
110
106
  ],
111
107
  "bugs": {
@@ -0,0 +1,30 @@
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: "...",
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(req, res) {
25
+ console.log(genomes, req, res);
26
+ };
27
+ }
28
+ export {
29
+ api
30
+ };
@@ -0,0 +1,149 @@
1
+ import lines2R from "#src/lines2R.js";
2
+ import path from "path";
3
+ import serverconfig from "#src/serverconfig.js";
4
+ import { write_file } from "#src/utils.js";
5
+ const api = {
6
+ endpoint: "burden",
7
+ methods: {
8
+ get: {
9
+ init({ genomes }) {
10
+ return async (req, res) => {
11
+ try {
12
+ const genome = genomes[req.query.genome];
13
+ if (!genome)
14
+ throw `invalid q.genome=${req.query.genome}`;
15
+ const q = req.query;
16
+ const ds = genome.datasets[q.dslabel];
17
+ if (!ds)
18
+ throw `invalid q.genome=${req.query.dslabel}`;
19
+ if (!ds.cohort.cumburden?.files)
20
+ throw `missing ds.cohort.cumburden.files`;
21
+ const estimates = await getBurdenEstimates(req, ds);
22
+ const { keys, rows } = formatPayload(estimates);
23
+ res.send({ status: "ok", keys, rows });
24
+ } catch (e) {
25
+ res.send({ status: "error", error: e.message || e });
26
+ }
27
+ };
28
+ },
29
+ request: {
30
+ typeId: "BurdenRequest"
31
+ },
32
+ response: {
33
+ typeId: "BurdenResponse"
34
+ },
35
+ examples: [
36
+ {
37
+ request: {
38
+ body: {
39
+ genome: "hg38",
40
+ // TODO: !!! use hg38-test and TermdbTest !!!
41
+ dslabel: "SJLife",
42
+ diaggrp: 5,
43
+ sex: 1,
44
+ white: 1,
45
+ agedx: 1,
46
+ bleo: 0,
47
+ etop: 0,
48
+ cisp: 0,
49
+ carbo: 0,
50
+ steriod: 0,
51
+ vcr: 0,
52
+ hdmtx: 0,
53
+ itmt: 0,
54
+ ced: 0,
55
+ dox: 0,
56
+ heart: 0,
57
+ brain: 0,
58
+ abd: 0,
59
+ pelvis: 0,
60
+ chest: 0
61
+ }
62
+ },
63
+ response: {
64
+ header: { status: 200 }
65
+ }
66
+ }
67
+ ]
68
+ }
69
+ }
70
+ };
71
+ async function getBurdenEstimates(q, ds) {
72
+ const infile = path.join(serverconfig.cachedir, Math.random().toString() + ".json");
73
+ for (const k in q.query) {
74
+ q.query[k] = Number(q.query[k]);
75
+ }
76
+ const data = Object.assign({}, defaults, q.query);
77
+ await write_file(infile, JSON.stringify(data));
78
+ const { fit, surv, sample } = ds.cohort.cumburden.files;
79
+ if (!fit || !surv || !sample)
80
+ throw `missing one or more of ds.cohort.burden.files.{fit, surv, sample}`;
81
+ const args = [
82
+ infile,
83
+ `${serverconfig.tpmasterdir}/${fit}`,
84
+ `${serverconfig.tpmasterdir}/${surv}`,
85
+ `${serverconfig.tpmasterdir}/${sample}`
86
+ ];
87
+ const Routput = await lines2R(path.join(serverconfig.binpath, "utils/burden.R"), [], args);
88
+ const estimates = JSON.parse(Routput[0]);
89
+ return estimates;
90
+ }
91
+ function formatPayload(estimates) {
92
+ const rawKeys = Object.keys(estimates[0]);
93
+ const outKeys = [];
94
+ const keys = [];
95
+ for (const k of rawKeys) {
96
+ if (k == "chc") {
97
+ keys.push(k);
98
+ outKeys.push(k);
99
+ } else {
100
+ const age = Number(k.slice(1).split(",")[0]);
101
+ if (age <= 60 && age % 2 == 0) {
102
+ keys.push(k);
103
+ outKeys.push(`burden${age}`);
104
+ }
105
+ }
106
+ }
107
+ const rows = [];
108
+ for (const v of estimates) {
109
+ rows.push(keys.map((k) => v[k]));
110
+ }
111
+ return { keys: outKeys, rows };
112
+ }
113
+ const defaults = Object.freeze({
114
+ diaggrp: 5,
115
+ sex: 0,
116
+ white: 1,
117
+ agedx: 1,
118
+ // chemotherapy
119
+ steriod: 0,
120
+ bleo: 0,
121
+ vcr: 0,
122
+ //12, // Vincristine
123
+ etop: 0,
124
+ //2500, // Etoposide
125
+ itmt: 0,
126
+ // Intrathecal methothrexate_grp: 0,
127
+ ced: 0,
128
+ //1.6, // Cyclophosphamide, 0.7692 mean 7692.
129
+ cisp: 0,
130
+ //300, // Cisplatin
131
+ dox: 0,
132
+ // Anthracycline, 3 mean 300 ml/m2
133
+ carbo: 0,
134
+ // Carboplatin
135
+ hdmtx: 0,
136
+ // High-Dose Methotrexate
137
+ // radiation
138
+ brain: 0,
139
+ //5.4,
140
+ chest: 0,
141
+ //2.4,
142
+ heart: 0,
143
+ pelvis: 0,
144
+ abd: 0
145
+ //2.4
146
+ });
147
+ export {
148
+ api
149
+ };
@@ -0,0 +1,266 @@
1
+ import * as mds2_init from "#src/mds2.init.js";
2
+ import * as mds3_init from "#src/mds3.init.js";
3
+ import * as common from "#shared/common.js";
4
+ const api = {
5
+ endpoint: "getDataset",
6
+ // should rename to simply 'dataset', method is based on HTTP method
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(req, res) {
25
+ try {
26
+ const genome = genomes[req.query.genome];
27
+ if (!genome)
28
+ throw "unknown genome";
29
+ if (!genome.datasets)
30
+ throw "genomeobj.datasets{} missing";
31
+ let ds;
32
+ for (const k in genome.datasets) {
33
+ if (k.toLowerCase() == req.query.dsname.toLowerCase()) {
34
+ ds = genome.datasets[k];
35
+ break;
36
+ }
37
+ }
38
+ if (!ds)
39
+ throw "invalid dsname";
40
+ if (ds.isMds3) {
41
+ return res.send({ ds: mds3_init.client_copy(ds) });
42
+ }
43
+ if (ds.isMds) {
44
+ return res.send({ ds: mds_clientcopy(ds) });
45
+ }
46
+ return res.send({ ds: copy_legacyDataset(ds) });
47
+ } catch (e) {
48
+ res.send({ error: e.message || e });
49
+ }
50
+ };
51
+ }
52
+ function mds_clientcopy(ds) {
53
+ const ds2 = {
54
+ isMds: true,
55
+ noHandleOnClient: ds.noHandleOnClient,
56
+ label: ds.label,
57
+ version: ds.version,
58
+ annotationsampleset2matrix: ds.annotationsampleset2matrix,
59
+ mutationAttribute: ds.mutationAttribute,
60
+ locusAttribute: ds.locusAttribute,
61
+ alleleAttribute: ds.alleleAttribute,
62
+ // these are quick fixes and should be deleted later
63
+ hide_genotypedownload: ds.hide_genotypedownload,
64
+ hide_phewas: ds.hide_phewas,
65
+ sample2bam: ds.sample2bam
66
+ };
67
+ if (ds.queries) {
68
+ ds2.queries = {};
69
+ }
70
+ if (ds.track) {
71
+ ds2.track = mds2_init.client_copy(ds);
72
+ }
73
+ if (ds.singlesamplemutationjson) {
74
+ ds2.singlesamplemutationjson = 1;
75
+ }
76
+ if (ds.gene2mutcount) {
77
+ ds2.gene2mutcount = true;
78
+ ds2.mutCountType = ds.gene2mutcount.mutationTypes;
79
+ }
80
+ if (ds.assayAvailability) {
81
+ ds2.assayAvailability = 1;
82
+ }
83
+ if (ds.cohort && ds.cohort.sampleAttribute) {
84
+ const toclient = {};
85
+ for (const k in ds.cohort.sampleAttribute.attributes) {
86
+ const a = ds.cohort.sampleAttribute.attributes[k];
87
+ if (!a.clientnoshow)
88
+ toclient[k] = a;
89
+ }
90
+ ds2.sampleAttribute = { attributes: toclient };
91
+ }
92
+ if (ds.cohort) {
93
+ if (ds.cohort.termdb) {
94
+ ds2.termdb = {
95
+ selectCohort: ds.cohort.termdb.selectCohort
96
+ };
97
+ }
98
+ if (ds.cohort.attributes && ds.cohort.attributes.defaulthidden) {
99
+ ds2.cohortHiddenAttr = ds.cohort.attributes.defaulthidden;
100
+ }
101
+ if (ds.cohort.survivalplot) {
102
+ ds2.survivalplot = {
103
+ samplegroupattrlst: ds.cohort.survivalplot.samplegroupattrlst,
104
+ plots: []
105
+ };
106
+ for (const k in ds.cohort.survivalplot.plots) {
107
+ const p = ds.cohort.survivalplot.plots[k];
108
+ ds2.survivalplot.plots.push({
109
+ key: k,
110
+ name: p.name,
111
+ timelabel: p.timelabel
112
+ });
113
+ }
114
+ }
115
+ if (ds.cohort.mutation_signature) {
116
+ const sets = {};
117
+ for (const k in ds.cohort.mutation_signature.sets) {
118
+ const s = ds.cohort.mutation_signature.sets[k];
119
+ sets[k] = {
120
+ name: s.name,
121
+ signatures: s.signatures
122
+ };
123
+ }
124
+ ds2.mutation_signature = { sets };
125
+ }
126
+ }
127
+ for (const k in ds.queries) {
128
+ const q = ds.queries[k];
129
+ const clientquery = {
130
+ // revealed to client
131
+ name: q.name,
132
+ hideforthemoment: q.hideforthemoment
133
+ // hide track not ready to show on client
134
+ };
135
+ if (q.istrack) {
136
+ clientquery.istrack = true;
137
+ clientquery.type = q.type;
138
+ clientquery.isfull = q.isfull;
139
+ if (q.nochr != void 0) {
140
+ clientquery.nochr = q.nochr;
141
+ }
142
+ if (q.infoFilter) {
143
+ clientquery.infoFilter = q.infoFilter;
144
+ }
145
+ if (q.readcountCutoff) {
146
+ clientquery.readcountCutoff = q.readcountCutoff;
147
+ }
148
+ if (q.valueLabel) {
149
+ clientquery.valueLabel = q.valueLabel;
150
+ }
151
+ if (q.valueCutoff) {
152
+ clientquery.valueCutoff = q.valueCutoff;
153
+ }
154
+ if (q.bplengthUpperLimit) {
155
+ clientquery.bplengthUpperLimit = q.bplengthUpperLimit;
156
+ }
157
+ if (q.segmeanValueCutoff) {
158
+ clientquery.segmeanValueCutoff = q.segmeanValueCutoff;
159
+ }
160
+ if (q.lohLengthUpperLimit) {
161
+ clientquery.lohLengthUpperLimit = q.lohLengthUpperLimit;
162
+ }
163
+ if (q.type == common.tkt.mdssvcnv) {
164
+ if (q.groupsamplebyattr) {
165
+ clientquery.groupsamplebyattr = q.groupsamplebyattr;
166
+ }
167
+ clientquery.multihidelabel_fusion = q.multihidelabel_fusion;
168
+ clientquery.multihidelabel_sv = q.multihidelabel_sv;
169
+ clientquery.multihidelabel_vcf = q.multihidelabel_vcf;
170
+ clientquery.showfullmode = q.showfullmode;
171
+ clientquery.legend_vorigin = q.legend_vorigin;
172
+ clientquery.no_loh = q.no_loh;
173
+ if (q.expressionrank_querykey) {
174
+ const e = ds.queries[q.expressionrank_querykey];
175
+ clientquery.checkexpressionrank = {
176
+ querykey: q.expressionrank_querykey,
177
+ datatype: e.datatype
178
+ };
179
+ if (e.boxplotbysamplegroup && e.boxplotbysamplegroup.additionals) {
180
+ const lst = [];
181
+ if (e.boxplotbysamplegroup.attributes)
182
+ lst.push(e.boxplotbysamplegroup.attributes.map((i) => i.label).join(", "));
183
+ for (const i of e.boxplotbysamplegroup.additionals)
184
+ lst.push(i.label);
185
+ clientquery.checkexpressionrank.boxplotgroupers = lst;
186
+ }
187
+ }
188
+ if (q.vcf_querykey) {
189
+ clientquery.checkvcf = {
190
+ querykey: q.vcf_querykey,
191
+ info: ds.queries[q.vcf_querykey].info,
192
+ format: {}
193
+ };
194
+ for (const tk of ds.queries[q.vcf_querykey].tracks) {
195
+ if (tk.format) {
196
+ for (const k2 in tk.format) {
197
+ clientquery.checkvcf.format[k2] = tk.format[k2];
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+ } else if (q.isgenenumeric) {
204
+ clientquery.isgenenumeric = true;
205
+ clientquery.datatype = q.datatype;
206
+ clientquery.no_ase = q.no_ase;
207
+ } else {
208
+ continue;
209
+ }
210
+ ds2.queries[k] = clientquery;
211
+ }
212
+ return ds2;
213
+ }
214
+ function copy_legacyDataset(ds) {
215
+ const ds2 = {
216
+ noHandleOnClient: ds.noHandleOnClient,
217
+ sampleselectable: ds.sampleselectable,
218
+ label: ds.label,
219
+ dsinfo: ds.dsinfo,
220
+ stratify: ds.stratify,
221
+ cohort: ds.cohort,
222
+ vcfinfofilter: ds.vcfinfofilter,
223
+ info2table: ds.info2table,
224
+ info2singletable: ds.info2singletable,
225
+ url4variant: ds.url4variant,
226
+ itemlabelname: ds.itemlabelname
227
+ };
228
+ if (ds.snvindel_attributes) {
229
+ ds2.snvindel_attributes = [];
230
+ for (const at of ds.snvindel_attributes) {
231
+ const rep = {};
232
+ for (const k in at) {
233
+ if (k == "lst") {
234
+ rep.lst = [];
235
+ for (const e of at.lst) {
236
+ const rep2 = {};
237
+ for (const k2 in e)
238
+ rep2[k2] = e[k2];
239
+ rep.lst.push(rep2);
240
+ }
241
+ } else {
242
+ rep[k] = at[k];
243
+ }
244
+ }
245
+ ds2.snvindel_attributes.push(rep);
246
+ }
247
+ }
248
+ if (ds.snvindel_legend) {
249
+ ds2.snvindel_legend = ds.snvindel_legend;
250
+ }
251
+ const vcfinfo = {};
252
+ let hasvcf = false;
253
+ for (const q of ds.queries) {
254
+ if (q.vcf) {
255
+ hasvcf = true;
256
+ vcfinfo[q.vcf.vcfid] = q.vcf;
257
+ }
258
+ }
259
+ if (hasvcf) {
260
+ ds2.id2vcf = vcfinfo;
261
+ }
262
+ return ds2;
263
+ }
264
+ export {
265
+ api
266
+ };
@@ -0,0 +1,127 @@
1
+ import path from "path";
2
+ import { spawn } from "child_process";
3
+ import serverconfig from "#src/serverconfig.js";
4
+ import * as common from "#shared/common.js";
5
+ const api = {
6
+ // route endpoint
7
+ // - no need for trailing slash
8
+ // - should be a noun (method is based on HTTP GET, POST, etc)
9
+ // - don't add 'Data' as response is assumed to be data
10
+ endpoint: "dsdata",
11
+ methods: {
12
+ get: {
13
+ init,
14
+ request: {
15
+ typeId: "any"
16
+ },
17
+ response: {
18
+ typeId: "any"
19
+ }
20
+ },
21
+ post: {
22
+ alternativeFor: "get",
23
+ init
24
+ }
25
+ }
26
+ };
27
+ function init({ genomes }) {
28
+ return async function handle_dsdata(req, res) {
29
+ try {
30
+ if (!genomes[req.query.genome])
31
+ throw "invalid genome";
32
+ if (!req.query.dsname)
33
+ throw ".dsname missing";
34
+ const ds = genomes[req.query.genome].datasets[req.query.dsname];
35
+ if (!ds)
36
+ throw "invalid dsname";
37
+ const data = [];
38
+ for (const query of ds.queries) {
39
+ if (req.query.expressiononly && !query.isgeneexpression) {
40
+ continue;
41
+ }
42
+ if (req.query.noexpression && query.isgeneexpression) {
43
+ continue;
44
+ }
45
+ if (query.dsblocktracklst) {
46
+ continue;
47
+ }
48
+ if (query.vcffile) {
49
+ const d = await handle_dsdata_vcf(query, req);
50
+ data.push(d);
51
+ continue;
52
+ }
53
+ if (query.makequery) {
54
+ const d = handle_dsdata_makequery(ds, query, req, genomes);
55
+ data.push(d);
56
+ continue;
57
+ }
58
+ throw "unknow type from one of ds.queries[]";
59
+ }
60
+ res.send({ data });
61
+ } catch (e) {
62
+ if (e.stack)
63
+ console.log(e.stack);
64
+ res.send({ error: e.message || e });
65
+ }
66
+ };
67
+ }
68
+ function handle_dsdata_makequery(ds, query, req, genomes) {
69
+ if (req.query.isoform) {
70
+ if (genomes[req.query.genome].genomicNameRegexp.test(req.query.isoform))
71
+ return;
72
+ }
73
+ const [sqlstr, values] = query.makequery(req.query);
74
+ if (!sqlstr) {
75
+ return;
76
+ }
77
+ const rows = ds.newconn.prepare(sqlstr).all(values);
78
+ let lst;
79
+ if (query.tidy) {
80
+ lst = rows.map((i) => query.tidy(i));
81
+ } else {
82
+ lst = rows;
83
+ }
84
+ const result = {};
85
+ if (query.isgeneexpression) {
86
+ result.lst = lst;
87
+ result.isgeneexpression = true;
88
+ result.config = query.config;
89
+ for (const q2 of ds.queries) {
90
+ if (!q2.dsblocktracklst)
91
+ continue;
92
+ for (const tk of q2.dsblocktracklst) {
93
+ if (tk.type == common.tkt.junction) {
94
+ result.config.dsjunctiontk = tk;
95
+ }
96
+ }
97
+ }
98
+ } else {
99
+ result.lst = lst;
100
+ }
101
+ return result;
102
+ }
103
+ function handle_dsdata_vcf(query, req) {
104
+ const par = [
105
+ path.join(serverconfig.tpmasterdir, query.vcffile),
106
+ (query.vcf.nochr ? req.query.range.chr.replace("chr", "") : req.query.range.chr) + ":" + req.query.range.start + "-" + req.query.range.stop
107
+ ];
108
+ return new Promise((resolve, reject) => {
109
+ const ps = spawn(serverconfig.tabix, par);
110
+ const out = [], out2 = [];
111
+ ps.stdout.on("data", (i) => out.push(i));
112
+ ps.stderr.on("data", (i) => out2.push(i));
113
+ ps.on("close", (code) => {
114
+ const e = out2.join("").trim();
115
+ if (e != "")
116
+ reject("error querying vcf file");
117
+ const tmp = out.join("").trim();
118
+ resolve({
119
+ lines: tmp == "" ? [] : tmp.split("\n"),
120
+ vcfid: query.vcf.vcfid
121
+ });
122
+ });
123
+ });
124
+ }
125
+ export {
126
+ api
127
+ };