@sjcrh/proteinpaint-server 2.98.1-0 → 2.98.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/package.json +2 -2
- package/routes/correlationVolcano.js +128 -0
- package/routes/termdb.config.js +14 -2
- package/src/app.js +1133 -830
- package/utils/corr.R +36 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjcrh/proteinpaint-server",
|
|
3
|
-
"version": "2.98.1
|
|
3
|
+
"version": "2.98.1",
|
|
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,7 +61,7 @@
|
|
|
61
61
|
"@sjcrh/augen": "2.87.0",
|
|
62
62
|
"@sjcrh/proteinpaint-rust": "2.84.0",
|
|
63
63
|
"@sjcrh/proteinpaint-shared": "2.98.0",
|
|
64
|
-
"@sjcrh/proteinpaint-types": "2.98.1
|
|
64
|
+
"@sjcrh/proteinpaint-types": "2.98.1",
|
|
65
65
|
"better-sqlite3": "^9.4.1",
|
|
66
66
|
"body-parser": "^1.15.2",
|
|
67
67
|
"canvas": "~2.11.2",
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { CorrelationVolcanoPayload } from "#types/checkers";
|
|
2
|
+
import { getData } from "../src/termdb.matrix.js";
|
|
3
|
+
import run_R from "../src/run_R.js";
|
|
4
|
+
import serverconfig from "../src/serverconfig.js";
|
|
5
|
+
import { mayLog } from "#src/helpers.ts";
|
|
6
|
+
import path from "path";
|
|
7
|
+
const api = {
|
|
8
|
+
endpoint: "termdb/correlationVolcano",
|
|
9
|
+
methods: {
|
|
10
|
+
get: {
|
|
11
|
+
...CorrelationVolcanoPayload,
|
|
12
|
+
init
|
|
13
|
+
},
|
|
14
|
+
post: {
|
|
15
|
+
...CorrelationVolcanoPayload,
|
|
16
|
+
init
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function init({ genomes }) {
|
|
21
|
+
return async (req, res) => {
|
|
22
|
+
const q = req.query;
|
|
23
|
+
try {
|
|
24
|
+
const genome = genomes[q.genome];
|
|
25
|
+
if (!genome)
|
|
26
|
+
throw "invalid genome name";
|
|
27
|
+
const ds = genome.datasets?.[q.dslabel];
|
|
28
|
+
if (!ds)
|
|
29
|
+
throw "invalid ds";
|
|
30
|
+
const result = await compute(q, ds, genome);
|
|
31
|
+
res.send(result);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
res.send({ error: e?.message || e });
|
|
34
|
+
if (e instanceof Error && e.stack)
|
|
35
|
+
console.error(e);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async function compute(q, ds, genome) {
|
|
40
|
+
const terms = [q.featureTw, ...q.variableTwLst];
|
|
41
|
+
const data = await getData(
|
|
42
|
+
{
|
|
43
|
+
filter: q.filter,
|
|
44
|
+
filter0: q.filter0,
|
|
45
|
+
terms
|
|
46
|
+
},
|
|
47
|
+
ds,
|
|
48
|
+
genome
|
|
49
|
+
);
|
|
50
|
+
if (data.error)
|
|
51
|
+
throw data.error;
|
|
52
|
+
const vtid2array = /* @__PURE__ */ new Map();
|
|
53
|
+
for (const tw of q.variableTwLst) {
|
|
54
|
+
vtid2array.set(tw.$id, { id: tw.$id, v1: [], v2: [] });
|
|
55
|
+
}
|
|
56
|
+
for (const sid in data.samples) {
|
|
57
|
+
const featureValue = data.samples[sid][q.featureTw.$id]?.value;
|
|
58
|
+
if (!Number.isFinite(featureValue))
|
|
59
|
+
continue;
|
|
60
|
+
for (const tw of q.variableTwLst) {
|
|
61
|
+
const variableValue = data.samples[sid][tw.$id]?.value;
|
|
62
|
+
if (!Number.isFinite(variableValue))
|
|
63
|
+
continue;
|
|
64
|
+
vtid2array.get(tw.$id).v1.push(featureValue);
|
|
65
|
+
vtid2array.get(tw.$id).v2.push(variableValue);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const input = {
|
|
69
|
+
method: q.correlationMethod || "pearson",
|
|
70
|
+
terms: [...vtid2array.values()]
|
|
71
|
+
};
|
|
72
|
+
const time1 = Date.now();
|
|
73
|
+
const r_output = await run_R(path.join(serverconfig.binpath, "utils", "corr.R"), JSON.stringify(input));
|
|
74
|
+
mayLog("Time taken to run correlation analysis:", Date.now() - time1);
|
|
75
|
+
let json_result;
|
|
76
|
+
for (const line of r_output.split("\n")) {
|
|
77
|
+
if (line.startsWith("adjusted_p_values:")) {
|
|
78
|
+
json_result = JSON.parse(line.replace("adjusted_p_values:", ""));
|
|
79
|
+
} else {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const output = { terms: json_result };
|
|
83
|
+
const result = { variableItems: [] };
|
|
84
|
+
for (const t of output.terms) {
|
|
85
|
+
const t2 = {
|
|
86
|
+
tw$id: t.id,
|
|
87
|
+
sampleSize: t.sample_size,
|
|
88
|
+
//sampleSize: input.terms.get(t.id).v1.length, // This was not working so passed the length of each array from R
|
|
89
|
+
correlation: t.correlation,
|
|
90
|
+
original_pvalue: t.original_p_value,
|
|
91
|
+
adjusted_pvalue: t.adjusted_p_value
|
|
92
|
+
};
|
|
93
|
+
result.variableItems.push(t2);
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
function validate_correlationVolcano(ds) {
|
|
98
|
+
const cv = ds.cohort.correlationVolcano;
|
|
99
|
+
if (!cv)
|
|
100
|
+
return;
|
|
101
|
+
if (typeof cv.feature != "object")
|
|
102
|
+
throw "cv.feature not obj";
|
|
103
|
+
if (cv.feature.termType == "geneExpression") {
|
|
104
|
+
if (!ds.queries?.geneExpression)
|
|
105
|
+
throw "cv.feature.termType=geneExpression not supported by ds";
|
|
106
|
+
} else {
|
|
107
|
+
throw "unknown cv.feature.termType";
|
|
108
|
+
}
|
|
109
|
+
if (typeof cv.variables != "object")
|
|
110
|
+
throw "cv.variables not obj";
|
|
111
|
+
if (cv.variables.type == "dictionaryTerm") {
|
|
112
|
+
if (!Array.isArray(cv.variables.termIds))
|
|
113
|
+
throw "cv.variables.termIds not array when type=dictionaryTerm";
|
|
114
|
+
for (const id of cv.variables.termIds) {
|
|
115
|
+
const t = ds.cohort.termdb.q.termjsonByOneid(id);
|
|
116
|
+
if (!t)
|
|
117
|
+
throw "cv.variables.termIds: unknown id: " + id;
|
|
118
|
+
if (t.type != "integer" && t.type != "float")
|
|
119
|
+
throw "cv.variables.termIds: not integer/float: " + id;
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
throw "unknown cv.variables.type";
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
api,
|
|
127
|
+
validate_correlationVolcano
|
|
128
|
+
};
|
package/routes/termdb.config.js
CHANGED
|
@@ -40,8 +40,7 @@ function init({ genomes }) {
|
|
|
40
40
|
function make(q, req, res, ds, genome) {
|
|
41
41
|
const tdb = ds.cohort.termdb;
|
|
42
42
|
const c = {
|
|
43
|
-
selectCohort:
|
|
44
|
-
// optional
|
|
43
|
+
selectCohort: getSelectCohort(ds, req),
|
|
45
44
|
supportedChartTypes: tdb.q?.getSupportedChartTypes(req),
|
|
46
45
|
renamedChartTypes: ds.cohort.renamedChartTypes,
|
|
47
46
|
allowedTermTypes: getAllowedTermTypes(ds),
|
|
@@ -93,6 +92,9 @@ function make(q, req, res, ds, genome) {
|
|
|
93
92
|
c.assayAvailability = ds.assayAvailability;
|
|
94
93
|
if (ds.customTwQByType)
|
|
95
94
|
c.customTwQByType = ds.customTwQByType;
|
|
95
|
+
if (ds.cohort.correlationVolcano)
|
|
96
|
+
c.correlationVolcano = ds.cohort.correlationVolcano;
|
|
97
|
+
c.requiredAuth = authApi.getRequiredCredForDsEmbedder(q.dslabel, q.embedder);
|
|
96
98
|
addRestrictAncestries(c, tdb);
|
|
97
99
|
addScatterplots(c, ds);
|
|
98
100
|
addMatrixplots(c, ds);
|
|
@@ -257,6 +259,16 @@ function getAllowedTermTypes(ds) {
|
|
|
257
259
|
typeSet.add(TermTypes.METABOLITE_INTENSITY);
|
|
258
260
|
return [...typeSet];
|
|
259
261
|
}
|
|
262
|
+
function getSelectCohort(ds, req) {
|
|
263
|
+
if (!ds.cohort.termdb.selectCohort)
|
|
264
|
+
return;
|
|
265
|
+
const copy = Object.assign({}, ds.cohort.termdb.selectCohort);
|
|
266
|
+
if (ds.cohort.termdb.selectCohort.descriptionByUser) {
|
|
267
|
+
copy.description = ds.cohort.termdb.selectCohort.descriptionByUser(authApi.getNonsensitiveInfo(req));
|
|
268
|
+
delete copy.descriptionByUser;
|
|
269
|
+
}
|
|
270
|
+
return copy;
|
|
271
|
+
}
|
|
260
272
|
export {
|
|
261
273
|
api
|
|
262
274
|
};
|