@sjcrh/proteinpaint-server 2.72.0 → 2.73.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 +2 -2
- package/routes/samplewsimages.js +4 -3
- package/routes/termdb.categories.js +1 -1
- package/routes/termdb.cluster.js +5 -5
- package/routes/termdb.getdescrstats.js +5 -1
- package/routes/termdb.termsbyids.js +1 -1
- package/routes/termdb.topVariablyExpressedGenes.js +70 -6
- package/src/app.js +267 -94
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjcrh/proteinpaint-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.73.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",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@sjcrh/augen": "2.46.0",
|
|
65
|
-
"@sjcrh/proteinpaint-rust": "2.
|
|
65
|
+
"@sjcrh/proteinpaint-rust": "2.73.0",
|
|
66
66
|
"better-sqlite3": "^9.4.1",
|
|
67
67
|
"body-parser": "^1.15.2",
|
|
68
68
|
"canvas": "~2.11.2",
|
package/routes/samplewsimages.js
CHANGED
|
@@ -22,13 +22,14 @@ const api = {
|
|
|
22
22
|
function init({ genomes }) {
|
|
23
23
|
return async (req, res) => {
|
|
24
24
|
try {
|
|
25
|
-
const
|
|
25
|
+
const query = req.query;
|
|
26
|
+
const g = genomes[query.genome];
|
|
26
27
|
if (!g)
|
|
27
28
|
throw "invalid genome name";
|
|
28
|
-
const ds = g.datasets[
|
|
29
|
+
const ds = g.datasets[query.dslabel];
|
|
29
30
|
if (!ds)
|
|
30
31
|
throw "invalid dataset name";
|
|
31
|
-
const sampleId =
|
|
32
|
+
const sampleId = query.sample_id;
|
|
32
33
|
const sampleWSImagesPath = path.join(
|
|
33
34
|
`${serverconfig.tpmasterdir}/${ds.queries.WSImages.imageBySampleFolder}`,
|
|
34
35
|
sampleId
|
|
@@ -92,7 +92,7 @@ async function trigger_getcategories(q, res, tdb, ds, genome) {
|
|
|
92
92
|
if (data.error)
|
|
93
93
|
throw data.error;
|
|
94
94
|
const lst = [];
|
|
95
|
-
if (q.tw.term.type == "geneVariant" &&
|
|
95
|
+
if (q.tw.term.type == "geneVariant" && q.tw.q.type != "predefined-groupset" && q.tw.q.type != "custom-groupset") {
|
|
96
96
|
const samples = data.samples;
|
|
97
97
|
const dtClassMap = /* @__PURE__ */ new Map();
|
|
98
98
|
if (ds.assayAvailability?.byDt) {
|
package/routes/termdb.cluster.js
CHANGED
|
@@ -192,11 +192,10 @@ async function validateNative(q, ds, genome) {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
const term2sample2value = /* @__PURE__ */ new Map();
|
|
195
|
-
for (const
|
|
196
|
-
const geneTerm = g;
|
|
195
|
+
for (const geneTerm of param.terms) {
|
|
197
196
|
if (!geneTerm.gene)
|
|
198
197
|
continue;
|
|
199
|
-
if (!geneTerm.chr) {
|
|
198
|
+
if (!geneTerm.chr || !Number.isInteger(geneTerm.start) || !Number.isInteger(geneTerm.stop)) {
|
|
200
199
|
const re = getResultGene(genome, { input: geneTerm.gene, deep: 1 });
|
|
201
200
|
if (!re.gmlst || re.gmlst.length == 0) {
|
|
202
201
|
console.warn("unknown gene:" + geneTerm.gene);
|
|
@@ -208,12 +207,13 @@ async function validateNative(q, ds, genome) {
|
|
|
208
207
|
geneTerm.chr = i.chr;
|
|
209
208
|
}
|
|
210
209
|
const s2v = {};
|
|
210
|
+
if (!geneTerm.chr || !Number.isInteger(geneTerm.start) || !Number.isInteger(geneTerm.stop))
|
|
211
|
+
throw "missing chr/start/stop";
|
|
211
212
|
await utils.get_lines_bigfile({
|
|
212
213
|
args: [
|
|
213
214
|
q.file,
|
|
214
|
-
(q.nochr ? geneTerm.chr
|
|
215
|
+
(q.nochr ? geneTerm.chr.replace("chr", "") : geneTerm.chr) + ":" + geneTerm.start + "-" + geneTerm.stop
|
|
215
216
|
],
|
|
216
|
-
// must do g.chr?.replace to avoid tsc error
|
|
217
217
|
callback: (line) => {
|
|
218
218
|
const l = line.split(" ");
|
|
219
219
|
if (l[3].toLowerCase() != geneTerm.gene.toLowerCase())
|
|
@@ -84,7 +84,11 @@ function init({ genomes }) {
|
|
|
84
84
|
}
|
|
85
85
|
values.push(Number(value));
|
|
86
86
|
}
|
|
87
|
-
|
|
87
|
+
if (values.length) {
|
|
88
|
+
result = Summarystats(values);
|
|
89
|
+
} else {
|
|
90
|
+
result = {};
|
|
91
|
+
}
|
|
88
92
|
} catch (e) {
|
|
89
93
|
if (e instanceof Error && e.stack)
|
|
90
94
|
console.log(e);
|
|
@@ -45,7 +45,7 @@ async function trigger_gettermsbyid(q, res, tdb) {
|
|
|
45
45
|
for (const id of q.ids) {
|
|
46
46
|
const term = tdb.q.termjsonByOneid(id);
|
|
47
47
|
if (term) {
|
|
48
|
-
if (term.type == "categorical" && !term.values
|
|
48
|
+
if (term.type == "categorical" && !term.values) {
|
|
49
49
|
term.values = {};
|
|
50
50
|
term.samplecount = {};
|
|
51
51
|
}
|
|
@@ -61,6 +61,7 @@ function nativeValidateQuery(ds) {
|
|
|
61
61
|
throw "topVariablyExpressedGenes query given but geneExpression missing";
|
|
62
62
|
if (gE.src != "native")
|
|
63
63
|
throw "topVariablyExpressedGenes is native but geneExpression.src is not native";
|
|
64
|
+
addTopVEarg(ds.queries.topVariablyExpressedGenes);
|
|
64
65
|
ds.queries.topVariablyExpressedGenes.getGenes = async (q) => {
|
|
65
66
|
const samples = [];
|
|
66
67
|
if (q.filter) {
|
|
@@ -81,18 +82,81 @@ function nativeValidateQuery(ds) {
|
|
|
81
82
|
samples.push(n);
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
const genes = await computeGenes4nativeDs(q,
|
|
85
|
+
const genes = await computeGenes4nativeDs(q, gE.file, samples);
|
|
85
86
|
return genes;
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
|
-
|
|
89
|
+
function addTopVEarg(q) {
|
|
90
|
+
const arglst = [
|
|
91
|
+
{ id: "maxGenes", label: "Gene Count", type: "number", value: 100 },
|
|
92
|
+
{
|
|
93
|
+
id: "filter_extreme_values",
|
|
94
|
+
label: "Filter Extreme Values",
|
|
95
|
+
type: "boolean",
|
|
96
|
+
value: true,
|
|
97
|
+
options: [
|
|
98
|
+
{
|
|
99
|
+
id: "min_count",
|
|
100
|
+
label: "Min count",
|
|
101
|
+
type: "number",
|
|
102
|
+
value: 10
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "min_total_count",
|
|
106
|
+
label: "Min total count",
|
|
107
|
+
type: "number",
|
|
108
|
+
value: 15
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "rank_type",
|
|
114
|
+
label: "Rank by:",
|
|
115
|
+
type: "radio",
|
|
116
|
+
options: [
|
|
117
|
+
/** The param option in input JSON is very important.
|
|
118
|
+
* It instructs what method will be used to calculate variation in the counts for a particular gene.
|
|
119
|
+
* It supports variance as well as interquartile region.
|
|
120
|
+
* This is based on the recommendation of this article:
|
|
121
|
+
* https://www.frontiersin.org/articles/10.3389/fgene.2021.632620/full.
|
|
122
|
+
* This article recommends using interquartile region over variance.*/
|
|
123
|
+
{
|
|
124
|
+
type: "boolean",
|
|
125
|
+
label: "Variance",
|
|
126
|
+
value: "var"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: "boolean",
|
|
130
|
+
label: "Interquartile Region",
|
|
131
|
+
value: "iqr"
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
];
|
|
136
|
+
if (q.arguments) {
|
|
137
|
+
for (const a of q.arguments) {
|
|
138
|
+
if (!a.id)
|
|
139
|
+
throw "missing id of topVE.arguments[]";
|
|
140
|
+
const item = arglst.find((i) => i.id == a.id);
|
|
141
|
+
if (!item)
|
|
142
|
+
throw "unknown id of topVE.arguments[]";
|
|
143
|
+
Object.assign(item, a);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
q.arguments = arglst;
|
|
147
|
+
}
|
|
148
|
+
async function computeGenes4nativeDs(q, matrixFile, samples) {
|
|
89
149
|
const input_json = {
|
|
90
150
|
input_file: matrixFile,
|
|
91
151
|
samples: samples.join(","),
|
|
92
|
-
filter_extreme_values:
|
|
152
|
+
filter_extreme_values: q.filter_extreme_values,
|
|
93
153
|
num_genes: q.maxGenes,
|
|
94
|
-
|
|
154
|
+
rank_type: q.rank_type?.type
|
|
95
155
|
};
|
|
156
|
+
if (q.filter_extreme_values == 1) {
|
|
157
|
+
input_json["min_count"] = q.min_count;
|
|
158
|
+
input_json["min_total_count"] = q.min_total_count;
|
|
159
|
+
}
|
|
96
160
|
const rust_output = await run_rust("topGeneByExpressionVariance", JSON.stringify(input_json));
|
|
97
161
|
const rust_output_list = rust_output.split("\n");
|
|
98
162
|
let output_json;
|
|
@@ -109,7 +173,7 @@ async function computeGenes4nativeDs(q, ds, matrixFile, samples) {
|
|
|
109
173
|
function gdcValidateQuery(ds, genome) {
|
|
110
174
|
ds.queries.topVariablyExpressedGenes.getGenes = async (q) => {
|
|
111
175
|
if (serverconfig.features.gdcGenes) {
|
|
112
|
-
console.
|
|
176
|
+
console.error(
|
|
113
177
|
"!!GDC!! using serverconfig.features.gdcGenes[] but not live api query. only use this on DEV and never on PROD!"
|
|
114
178
|
);
|
|
115
179
|
return serverconfig.features.gdcGenes;
|
|
@@ -142,7 +206,7 @@ function gdcValidateQuery(ds, genome) {
|
|
|
142
206
|
}
|
|
143
207
|
return genes;
|
|
144
208
|
} catch (e) {
|
|
145
|
-
console.
|
|
209
|
+
console.error(e.stack || e);
|
|
146
210
|
throw e;
|
|
147
211
|
}
|
|
148
212
|
};
|