@sjcrh/proteinpaint-server 2.155.0 → 2.157.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/package.json +5 -5
- package/routes/grin2.js +20 -8
- package/routes/termdb.DE.js +18 -18
- package/routes/termdb.singlecellDEgenes.js +6 -5
- package/src/app.js +56 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjcrh/proteinpaint-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.157.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "a genomics visualization tool for exploring a cohort's genotype and phenotype data",
|
|
6
6
|
"main": "src/app.js",
|
|
@@ -61,11 +61,11 @@
|
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@sjcrh/augen": "2.143.0",
|
|
64
|
-
"@sjcrh/proteinpaint-python": "2.
|
|
64
|
+
"@sjcrh/proteinpaint-python": "2.157.0",
|
|
65
65
|
"@sjcrh/proteinpaint-r": "2.152.1-0",
|
|
66
|
-
"@sjcrh/proteinpaint-rust": "2.
|
|
67
|
-
"@sjcrh/proteinpaint-shared": "2.
|
|
68
|
-
"@sjcrh/proteinpaint-types": "2.
|
|
66
|
+
"@sjcrh/proteinpaint-rust": "2.157.0",
|
|
67
|
+
"@sjcrh/proteinpaint-shared": "2.157.0",
|
|
68
|
+
"@sjcrh/proteinpaint-types": "2.157.0",
|
|
69
69
|
"@types/express": "^5.0.0",
|
|
70
70
|
"@types/express-session": "^1.18.1",
|
|
71
71
|
"better-sqlite3": "^12.4.1",
|
package/routes/grin2.js
CHANGED
|
@@ -2,6 +2,7 @@ import { GRIN2Payload } from "#types/checkers";
|
|
|
2
2
|
import serverconfig from "#src/serverconfig.js";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { run_python } from "@sjcrh/proteinpaint-python";
|
|
5
|
+
import { run_rust } from "@sjcrh/proteinpaint-rust";
|
|
5
6
|
import { mayLog } from "#src/helpers.ts";
|
|
6
7
|
import { get_samples } from "#src/termdb.sql.js";
|
|
7
8
|
import { read_file, file_is_readable } from "#src/utils.js";
|
|
@@ -88,10 +89,6 @@ async function runGrin2(g, ds, request) {
|
|
|
88
89
|
genedb: path.join(serverconfig.tpmasterdir, g.genedb.dbfile),
|
|
89
90
|
chromosomelist: {},
|
|
90
91
|
lesion: JSON.stringify(lesions),
|
|
91
|
-
devicePixelRatio: request.devicePixelRatio,
|
|
92
|
-
pngDotRadius: request.pngDotRadius,
|
|
93
|
-
width: request.width,
|
|
94
|
-
height: request.height,
|
|
95
92
|
cacheFileName: generateCacheFileName(),
|
|
96
93
|
availableDataTypes: getAvailableDataTypes(request),
|
|
97
94
|
maxGenesToShow: request.maxGenesToShow
|
|
@@ -114,14 +111,29 @@ async function runGrin2(g, ds, request) {
|
|
|
114
111
|
const grin2AnalysisTimeToPrint = Math.round(grin2AnalysisTime / 1e3);
|
|
115
112
|
mayLog(`[GRIN2] Python processing took ${grin2AnalysisTimeToPrint} seconds`);
|
|
116
113
|
const resultData = JSON.parse(pyResult);
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
const rustInput = {
|
|
115
|
+
file: resultData.cacheFileName,
|
|
116
|
+
type: "grin2",
|
|
117
|
+
chrSizes: pyInput.chromosomelist,
|
|
118
|
+
plot_width: request.width,
|
|
119
|
+
plot_height: request.height,
|
|
120
|
+
device_pixel_ratio: request.devicePixelRatio,
|
|
121
|
+
png_dot_radius: request.pngDotRadius
|
|
122
|
+
};
|
|
123
|
+
const manhattanPlotStart = Date.now();
|
|
124
|
+
const rsResult = await run_rust("manhattan_plot", JSON.stringify(rustInput));
|
|
125
|
+
const manhattanPlotTime = Date.now() - manhattanPlotStart;
|
|
126
|
+
const manhattanPlotTimeToPrint = Math.round(manhattanPlotTime / 1e3);
|
|
127
|
+
mayLog(`[GRIN2] Manhattan plot generation took ${manhattanPlotTimeToPrint} seconds`);
|
|
128
|
+
const manhattanPlotData = JSON.parse(rsResult);
|
|
129
|
+
if (!manhattanPlotData?.png) {
|
|
130
|
+
throw new Error("Invalid Rust output: missing PNG data");
|
|
119
131
|
}
|
|
120
132
|
const totalTime = Math.round((Date.now() - startTime) / 1e3);
|
|
121
133
|
const response = {
|
|
122
134
|
status: "success",
|
|
123
|
-
pngImg:
|
|
124
|
-
plotData:
|
|
135
|
+
pngImg: manhattanPlotData.png,
|
|
136
|
+
plotData: manhattanPlotData.plot_data,
|
|
125
137
|
topGeneTable: resultData.topGeneTable,
|
|
126
138
|
totalGenes: resultData.totalGenes,
|
|
127
139
|
showingTop: resultData.showingTop,
|
package/routes/termdb.DE.js
CHANGED
|
@@ -11,7 +11,7 @@ import imagesize from "image-size";
|
|
|
11
11
|
import { get_header_txt } from "#src/utils.js";
|
|
12
12
|
import { formatElapsedTime } from "@sjcrh/proteinpaint-shared/time.js";
|
|
13
13
|
const api = {
|
|
14
|
-
endpoint: "
|
|
14
|
+
endpoint: "termdb/DE",
|
|
15
15
|
methods: {
|
|
16
16
|
get: {
|
|
17
17
|
...diffExpPayload,
|
|
@@ -28,7 +28,7 @@ function init({ genomes }) {
|
|
|
28
28
|
try {
|
|
29
29
|
const q = req.query;
|
|
30
30
|
const genome = genomes[q.genome];
|
|
31
|
-
if (!genome) throw "invalid genome";
|
|
31
|
+
if (!genome) throw new Error("invalid genome");
|
|
32
32
|
const [ds] = get_ds_tdb(genome, q);
|
|
33
33
|
let term_results = [];
|
|
34
34
|
if (q.tw) {
|
|
@@ -41,7 +41,7 @@ function init({ genomes }) {
|
|
|
41
41
|
},
|
|
42
42
|
ds
|
|
43
43
|
);
|
|
44
|
-
if (term_results.error) throw term_results.error;
|
|
44
|
+
if (term_results.error) throw new Error(term_results.error);
|
|
45
45
|
}
|
|
46
46
|
let term_results2 = [];
|
|
47
47
|
if (q.tw2) {
|
|
@@ -54,10 +54,10 @@ function init({ genomes }) {
|
|
|
54
54
|
},
|
|
55
55
|
ds
|
|
56
56
|
);
|
|
57
|
-
if (term_results2.error) throw term_results2.error;
|
|
57
|
+
if (term_results2.error) throw new Error(term_results2.error);
|
|
58
58
|
}
|
|
59
59
|
const results = await run_DE(req.query, ds, term_results, term_results2);
|
|
60
|
-
if (!results || !results.data) throw "No data
|
|
60
|
+
if (!results || !results.data) throw new Error("No data available");
|
|
61
61
|
res.send(results);
|
|
62
62
|
} catch (e) {
|
|
63
63
|
res.send({ status: "error", error: e.message || e });
|
|
@@ -66,13 +66,13 @@ function init({ genomes }) {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
async function run_DE(param, ds, term_results, term_results2) {
|
|
69
|
-
if (param.samplelst?.groups?.length != 2) throw ".samplelst.groups.length!=2";
|
|
70
|
-
if (param.samplelst.groups[0].values?.length < 1) throw "samplelst.groups[0].values.length<1";
|
|
71
|
-
if (param.samplelst.groups[1].values?.length < 1) throw "samplelst.groups[1].values.length<1";
|
|
69
|
+
if (param.samplelst?.groups?.length != 2) throw new Error(".samplelst.groups.length!=2");
|
|
70
|
+
if (param.samplelst.groups[0].values?.length < 1) throw new Error("samplelst.groups[0].values.length<1");
|
|
71
|
+
if (param.samplelst.groups[1].values?.length < 1) throw new Error("samplelst.groups[1].values.length<1");
|
|
72
72
|
const q = ds.queries.rnaseqGeneCount;
|
|
73
73
|
if (!q) return;
|
|
74
|
-
if (!q.file) throw "unknown data type for rnaseqGeneCount";
|
|
75
|
-
if (!q.storage_type) throw "storage_type is not defined";
|
|
74
|
+
if (!q.file) throw new Error("unknown data type for rnaseqGeneCount");
|
|
75
|
+
if (!q.storage_type) throw new Error("storage_type is not defined");
|
|
76
76
|
param.storage_type = q.storage_type;
|
|
77
77
|
const group1names = [];
|
|
78
78
|
const conf1_group1 = [];
|
|
@@ -178,7 +178,7 @@ async function run_DE(param, ds, term_results, term_results2) {
|
|
|
178
178
|
}
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
|
-
if (alerts.length) throw alerts.join(" | ");
|
|
181
|
+
if (alerts.length) throw new Error(alerts.join(" | "));
|
|
182
182
|
const cases_string = group2names.map((i) => i).join(",");
|
|
183
183
|
const controls_string = group1names.map((i) => i).join(",");
|
|
184
184
|
const expression_input = {
|
|
@@ -199,14 +199,14 @@ async function run_DE(param, ds, term_results, term_results2) {
|
|
|
199
199
|
expression_input.conf1 = [...conf1_group2, ...conf1_group1];
|
|
200
200
|
expression_input.conf1_mode = param.tw.q.mode;
|
|
201
201
|
if (new Set(expression_input.conf1).size === 1) {
|
|
202
|
-
throw "Confounding variable 1 has only one value";
|
|
202
|
+
throw new Error("Confounding variable 1 has only one value");
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
if (param.tw2) {
|
|
206
206
|
expression_input.conf2 = [...conf2_group2, ...conf2_group1];
|
|
207
207
|
expression_input.conf2_mode = param.tw2.q.mode;
|
|
208
208
|
if (new Set(expression_input.conf2).size === 1) {
|
|
209
|
-
throw "Confounding variable 2 has only one value";
|
|
209
|
+
throw new Error("Confounding variable 2 has only one value");
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
const sample_size_limit = 8;
|
|
@@ -261,13 +261,13 @@ async function readFileAndDelete(file, key, response) {
|
|
|
261
261
|
};
|
|
262
262
|
response[key] = obj;
|
|
263
263
|
fs.unlink(file, (err) => {
|
|
264
|
-
if (err) throw err;
|
|
264
|
+
if (err) throw new Error(err.message || String(err));
|
|
265
265
|
});
|
|
266
266
|
}
|
|
267
267
|
async function validate_query_rnaseqGeneCount(ds) {
|
|
268
268
|
const q = ds.queries.rnaseqGeneCount;
|
|
269
269
|
if (!q) return;
|
|
270
|
-
if (!q.file) throw "unknown data type for rnaseqGeneCount";
|
|
270
|
+
if (!q.file) throw new Error("unknown data type for rnaseqGeneCount");
|
|
271
271
|
q.file = path.join(serverconfig.tpmasterdir, q.file);
|
|
272
272
|
{
|
|
273
273
|
let samples = [];
|
|
@@ -283,10 +283,10 @@ async function validate_query_rnaseqGeneCount(ds) {
|
|
|
283
283
|
const time2 = (/* @__PURE__ */ new Date()).valueOf();
|
|
284
284
|
mayLog("Time taken to query gene expression:", time2 - time1, "ms");
|
|
285
285
|
const vr = JSON.parse(result);
|
|
286
|
-
if (vr.status !== "success") throw vr.message;
|
|
287
|
-
if (!Array.isArray(vr.samples)) throw "HDF5 file has no samples, please check file.";
|
|
286
|
+
if (vr.status !== "success") throw new Error(vr.message);
|
|
287
|
+
if (!Array.isArray(vr.samples)) throw new Error("HDF5 file has no samples, please check file.");
|
|
288
288
|
samples = vr.samples;
|
|
289
|
-
} else throw "unknown storage type:" + ds.queries.rnaseqGeneCount.storage_type;
|
|
289
|
+
} else throw new Error("unknown storage type:" + ds.queries.rnaseqGeneCount.storage_type);
|
|
290
290
|
q.allSampleSet = new Set(samples);
|
|
291
291
|
const unknownSamples = [];
|
|
292
292
|
for (const n of q.allSampleSet) {
|
|
@@ -19,12 +19,13 @@ function init({ genomes }) {
|
|
|
19
19
|
let result;
|
|
20
20
|
try {
|
|
21
21
|
const g = genomes[q.genome];
|
|
22
|
-
if (!g) throw "invalid genome name";
|
|
22
|
+
if (!g) throw new Error("invalid genome name");
|
|
23
23
|
const ds = g.datasets[q.dslabel];
|
|
24
|
-
if (!ds) throw "invalid dataset name";
|
|
25
|
-
if (!ds.queries?.singleCell?.DEgenes
|
|
24
|
+
if (!ds) throw new Error("invalid dataset name");
|
|
25
|
+
if (!ds.queries?.singleCell?.DEgenes || !ds.queries.singleCell.DEgenes.get)
|
|
26
|
+
throw new Error("DE genes not supported on this dataset.");
|
|
26
27
|
result = await ds.queries.singleCell.DEgenes.get(q);
|
|
27
|
-
if (!result || !result.
|
|
28
|
+
if (!result || !result.data || !result?.data?.length) {
|
|
28
29
|
result = {
|
|
29
30
|
status: 404,
|
|
30
31
|
error: !result ? "No data found." : "No differentially expressed genes found."
|
|
@@ -44,7 +45,7 @@ async function validate_query_singleCell_DEgenes(ds) {
|
|
|
44
45
|
if (ds.queries.singleCell.DEgenes.src == "gdcapi") {
|
|
45
46
|
gdc_validate_query_singleCell_DEgenes(ds);
|
|
46
47
|
} else {
|
|
47
|
-
throw "unknown singleCell.DEgenes.src";
|
|
48
|
+
throw new Error("unknown singleCell.DEgenes.src");
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
export {
|