@sjcrh/proteinpaint-server 2.109.1 → 2.110.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 +3 -3
- package/routes/gdc.mafBuild.js +20 -13
- package/routes/termdb.DE.js +31 -9
- package/routes/termdb.boxplot.js +2 -1
- package/routes/termdb.violin.js +2 -1
- package/src/app.js +70 -39
- package/utils/edge.R +53 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjcrh/proteinpaint-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.110.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",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@sjcrh/augen": "2.109.1-0",
|
|
63
|
-
"@sjcrh/proteinpaint-rust": "2.
|
|
63
|
+
"@sjcrh/proteinpaint-rust": "2.110.0",
|
|
64
64
|
"@sjcrh/proteinpaint-shared": "2.109.1",
|
|
65
|
-
"@sjcrh/proteinpaint-types": "2.
|
|
65
|
+
"@sjcrh/proteinpaint-types": "2.110.0",
|
|
66
66
|
"@types/express": "^5.0.0",
|
|
67
67
|
"@types/express-session": "^1.18.1",
|
|
68
68
|
"better-sqlite3": "^9.4.1",
|
package/routes/gdc.mafBuild.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ky from "ky";
|
|
2
2
|
import { joinUrl } from "#shared/joinUrl.js";
|
|
3
|
-
import {
|
|
3
|
+
import { stream_rust } from "@sjcrh/proteinpaint-rust";
|
|
4
4
|
import { gdcMafPayload } from "#types/checkers";
|
|
5
5
|
import { maxTotalSizeCompressed } from "./gdc.maf.ts";
|
|
6
6
|
import { mayLog } from "#src/helpers.ts";
|
|
@@ -46,19 +46,26 @@ async function buildMaf(q, res, ds) {
|
|
|
46
46
|
host: joinUrl(host.rest, "data")
|
|
47
47
|
// must use the /data/ endpoint from current host
|
|
48
48
|
};
|
|
49
|
-
const
|
|
50
|
-
res.setHeader("
|
|
51
|
-
res.
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
const boundary = "GDC_MAF_MULTIPART_BOUNDARY";
|
|
50
|
+
res.setHeader("content-type", `multipart/mixed; boundary=${boundary}`);
|
|
51
|
+
res.write(`--${boundary}`);
|
|
52
|
+
res.write("\ncontent-disposition: attachment; filename=cohort.maf.gz");
|
|
53
|
+
res.write("\ncontent-type: application/octet-stream\n\n");
|
|
54
|
+
res.flush();
|
|
55
|
+
const rustStream = stream_rust("gdcmaf", JSON.stringify(arg), emitJson);
|
|
56
|
+
rustStream.pipe(res, { end: false });
|
|
57
|
+
function emitJson(data, end = true) {
|
|
58
|
+
res.write(`
|
|
59
|
+
--${boundary}`);
|
|
60
|
+
res.write("\ncontent-type: application/json");
|
|
61
|
+
const json = typeof data === "string" ? data : JSON.stringify(data || { ok: true, status: "ok" });
|
|
62
|
+
res.write("\n\n" + json);
|
|
63
|
+
res.write(`
|
|
64
|
+
--${boundary}--`);
|
|
54
65
|
mayLog("rust gdcmaf", Date.now() - t0);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
console.error(err);
|
|
59
|
-
res.statusCode = 500;
|
|
60
|
-
res.end("Internal Server Error");
|
|
61
|
-
});
|
|
66
|
+
if (end)
|
|
67
|
+
res.end();
|
|
68
|
+
}
|
|
62
69
|
}
|
|
63
70
|
async function getFileLstUnderSizeLimit(lst, host) {
|
|
64
71
|
if (lst.length == 0)
|
package/routes/termdb.DE.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fs from "fs";
|
|
1
2
|
import path from "path";
|
|
2
3
|
import { diffExpPayload } from "#types/checkers";
|
|
3
4
|
import { run_rust } from "@sjcrh/proteinpaint-rust";
|
|
@@ -188,6 +189,7 @@ async function run_DE(param, ds, term_results, term_results2) {
|
|
|
188
189
|
control: cases_string,
|
|
189
190
|
data_type: "do_DE",
|
|
190
191
|
input_file: q.file,
|
|
192
|
+
cachedir: serverconfig.cachedir,
|
|
191
193
|
min_count: param.min_count,
|
|
192
194
|
min_total_count: param.min_total_count,
|
|
193
195
|
storage_type: param.storage_type
|
|
@@ -207,25 +209,45 @@ async function run_DE(param, ds, term_results, term_results2) {
|
|
|
207
209
|
}
|
|
208
210
|
}
|
|
209
211
|
const sample_size_limit = 8;
|
|
210
|
-
let result;
|
|
211
212
|
if (group1names.length <= sample_size_limit && group2names.length <= sample_size_limit || param.method == "edgeR") {
|
|
212
213
|
if (param.method == "edgeR") {
|
|
213
214
|
expression_input.VarGenes = param.VarGenes;
|
|
214
215
|
}
|
|
215
|
-
const
|
|
216
|
-
|
|
216
|
+
const time12 = (/* @__PURE__ */ new Date()).valueOf();
|
|
217
|
+
const result2 = JSON.parse(
|
|
217
218
|
await run_R(path.join(serverconfig.binpath, "utils", "edge.R"), JSON.stringify(expression_input))
|
|
218
219
|
);
|
|
219
|
-
mayLog("Time taken to run edgeR:", Date.now() -
|
|
220
|
+
mayLog("Time taken to run edgeR:", Date.now() - time12, "ms");
|
|
220
221
|
param.method = "edgeR";
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
mayLog("
|
|
225
|
-
|
|
222
|
+
const ql_imagePath = path.join(serverconfig.cachedir, result2.edgeR_ql_image_name[0]);
|
|
223
|
+
mayLog("ql_imagePath:", ql_imagePath);
|
|
224
|
+
const mds_imagePath = path.join(serverconfig.cachedir, result2.edgeR_mds_image_name[0]);
|
|
225
|
+
mayLog("mds_imagePath:", mds_imagePath);
|
|
226
|
+
const mds_base64Image = await readFileAndDelete(mds_imagePath);
|
|
227
|
+
const ql_base64Image = await readFileAndDelete(ql_imagePath);
|
|
228
|
+
return {
|
|
229
|
+
data: result2.gene_data,
|
|
230
|
+
sample_size1,
|
|
231
|
+
sample_size2,
|
|
232
|
+
method: param.method,
|
|
233
|
+
ql_image: ql_base64Image,
|
|
234
|
+
// QL fit image
|
|
235
|
+
mds_image: mds_base64Image
|
|
236
|
+
// MDS image
|
|
237
|
+
};
|
|
226
238
|
}
|
|
239
|
+
const time1 = (/* @__PURE__ */ new Date()).valueOf();
|
|
240
|
+
const result = JSON.parse(await run_rust("DEanalysis", JSON.stringify(expression_input)));
|
|
241
|
+
mayLog("Time taken to run rust DE pipeline:", Date.now() - time1, "ms");
|
|
242
|
+
param.method = "wilcoxon";
|
|
227
243
|
return { data: result, sample_size1, sample_size2, method: param.method };
|
|
228
244
|
}
|
|
245
|
+
async function readFileAndDelete(file) {
|
|
246
|
+
const data = await fs.promises.readFile(file);
|
|
247
|
+
fs.unlink(file, () => {
|
|
248
|
+
});
|
|
249
|
+
return Buffer.from(data).toString("base64");
|
|
250
|
+
}
|
|
229
251
|
export {
|
|
230
252
|
api
|
|
231
253
|
};
|
package/routes/termdb.boxplot.js
CHANGED
|
@@ -3,6 +3,7 @@ import { getData } from "../src/termdb.matrix.js";
|
|
|
3
3
|
import { boxplot_getvalue } from "../src/utils.js";
|
|
4
4
|
import { sortKey2values } from "./termdb.violin.ts";
|
|
5
5
|
import { roundValueAuto } from "#shared/roundValue.js";
|
|
6
|
+
const minSampleSize = 5;
|
|
6
7
|
const api = {
|
|
7
8
|
endpoint: "termdb/boxplot",
|
|
8
9
|
methods: {
|
|
@@ -124,7 +125,7 @@ function setHiddenPlots(term, plots) {
|
|
|
124
125
|
return plots;
|
|
125
126
|
}
|
|
126
127
|
function setDescrStats(boxplot, sortedValues) {
|
|
127
|
-
if (sortedValues.length <
|
|
128
|
+
if (sortedValues.length < minSampleSize)
|
|
128
129
|
return [{ id: "total", label: "Total", value: sortedValues.length }];
|
|
129
130
|
const mean = sortedValues.reduce((s2, i) => s2 + i, 0) / sortedValues.length;
|
|
130
131
|
let s = 0;
|
package/routes/termdb.violin.js
CHANGED
|
@@ -8,6 +8,7 @@ import summaryStats from "#shared/descriptive.stats.js";
|
|
|
8
8
|
import { isNumericTerm } from "#shared/terms.js";
|
|
9
9
|
import { getBinsDensity } from "#shared/violin.bins.js";
|
|
10
10
|
import { numericBins, parseValues } from "./termdb.boxplot.ts";
|
|
11
|
+
const minSampleSize = 5;
|
|
11
12
|
const api = {
|
|
12
13
|
endpoint: "termdb/violin",
|
|
13
14
|
methods: {
|
|
@@ -193,7 +194,7 @@ function createCanvasImg(q, result, ds) {
|
|
|
193
194
|
ctx.strokeStyle = "rgba(0,0,0,0.8)";
|
|
194
195
|
ctx.lineWidth = q.strokeWidth / q.devicePixelRatio;
|
|
195
196
|
ctx.globalAlpha = 0.5;
|
|
196
|
-
ctx.fillStyle = "#ffe6e6";
|
|
197
|
+
ctx.fillStyle = plot.values.length <= minSampleSize ? "black" : "#ffe6e6";
|
|
197
198
|
if (q.devicePixelRatio != 1) {
|
|
198
199
|
ctx.scale(q.devicePixelRatio, q.devicePixelRatio);
|
|
199
200
|
}
|