@sjcrh/proteinpaint-server 2.188.1 → 2.190.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 +9 -12
- package/routes/aiProjectAdmin.js +2 -28
- package/routes/aiProjectSelectedWSImages.js +2 -17
- package/routes/brainImaging.js +1 -15
- package/routes/brainImagingSamples.js +1 -15
- package/routes/burden.js +1 -15
- package/routes/correlationVolcano.js +1 -15
- package/routes/dataset.js +1 -16
- package/routes/deleteWSITileSelection.js +2 -12
- package/routes/dsdata.js +1 -19
- package/routes/gdc.grin2.list.js +1 -15
- package/routes/gdc.grin2.run.js +1 -15
- package/routes/gdc.maf.js +1 -15
- package/routes/gdc.mafBuild.js +1 -15
- package/routes/genesetEnrichment.js +129 -97
- package/routes/grin2.js +110 -79
- package/routes/saveWSIAnnotation.js +2 -13
- package/routes/termdb.DE.js +137 -54
- package/routes/termdb.categories.js +2 -16
- package/routes/termdb.chat.js +169 -1076
- package/routes/termdb.cluster.js +5 -16
- package/routes/termdb.config.js +12 -17
- package/routes/termdb.descrstats.js +2 -16
- package/routes/termdb.diffMeth.js +100 -21
- package/routes/termdb.geneRanking.js +139 -0
- package/routes/termdb.proteome.js +1 -15
- package/routes/termdb.runChart.js +16 -30
- package/routes/termdb.sampleScatter.js +7 -97
- package/routes/termdb.singleCellPlots.js +159 -0
- package/routes/termdb.singlecellSamples.js +6 -16
- package/routes/termdb.violinBox.js +1 -15
- package/routes/wsimages.js +1 -16
- package/src/app.js +4014 -4127
- package/routes/_template_.js +0 -33
- package/routes/aiProjectTrainModel.js +0 -68
- package/routes/alphaGenome.js +0 -41
- package/routes/alphaGenomeTypes.js +0 -36
- package/routes/dzimages.js +0 -55
- package/routes/gene2canonicalisoform.js +0 -37
- package/routes/genelookup.js +0 -32
- package/routes/genesetOverrepresentation.js +0 -49
- package/routes/genomes.js +0 -150
- package/routes/healthcheck.js +0 -35
- package/routes/hicdata.js +0 -74
- package/routes/hicgenome.js +0 -75
- package/routes/hicstat.js +0 -35
- package/routes/img.js +0 -46
- package/routes/isoformlst.js +0 -48
- package/routes/ntseq.js +0 -36
- package/routes/pdomain.js +0 -53
- package/routes/profile.barchart2.js +0 -114
- package/routes/profile.forms2.js +0 -107
- package/routes/profile.polar2.js +0 -101
- package/routes/profile.radar2.js +0 -112
- package/routes/profile.radarFacility2.js +0 -148
- package/routes/sampledzimages.js +0 -48
- package/routes/samplewsimages.js +0 -60
- package/routes/snp.js +0 -98
- package/routes/termdb.chat2.js +0 -217
- package/routes/termdb.chat3.js +0 -209
- package/routes/termdb.cohort.summary.js +0 -37
- package/routes/termdb.cohorts.js +0 -41
- package/routes/termdb.dapVolcano.js +0 -80
- package/routes/termdb.dmr.js +0 -93
- package/routes/termdb.filterTermValues.js +0 -89
- package/routes/termdb.isoformAvailability.js +0 -35
- package/routes/termdb.numericcategories.js +0 -46
- package/routes/termdb.percentile.js +0 -66
- package/routes/termdb.profileFormScores.js +0 -92
- package/routes/termdb.profileScores.js +0 -113
- package/routes/termdb.rootterm.js +0 -39
- package/routes/termdb.sampleImages.js +0 -63
- package/routes/termdb.singleSampleMutation.js +0 -75
- package/routes/termdb.singlecellDEgenes.js +0 -55
- package/routes/termdb.singlecellData.js +0 -39
- package/routes/termdb.termchildren.js +0 -42
- package/routes/termdb.termsbyids.js +0 -50
- package/routes/termdb.topMutatedGenes.js +0 -127
- package/routes/termdb.topTermsByType.js +0 -96
- package/routes/termdb.topVariablyExpressedGenes.js +0 -132
- package/routes/tileserver.js +0 -68
- package/routes/wsisamples.js +0 -71
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { getColors, getCoordinate, calculatePadding, xAxisOffSet, yAxisOffSet } from "#shared";
|
|
2
|
+
import { isSingleCellTerm, SINGLECELL_GENE_EXPRESSION, SINGLECELL_CELLTYPE } from "#shared/terms.js";
|
|
3
|
+
import { createCanvas } from "canvas";
|
|
4
|
+
import { scaleLinear } from "d3-scale";
|
|
5
|
+
import { rgb } from "d3-color";
|
|
6
|
+
import { refColor } from "./termdb.sampleScatter.js";
|
|
7
|
+
function init({ genomes }) {
|
|
8
|
+
return async function(req, res) {
|
|
9
|
+
try {
|
|
10
|
+
const q = req.query;
|
|
11
|
+
if (!q.genome || !q.dslabel) {
|
|
12
|
+
throw new Error("Genome and dataset label are required for termdb/singleCellPlots request.");
|
|
13
|
+
}
|
|
14
|
+
const g = genomes[q.genome];
|
|
15
|
+
if (!g) throw new Error("Invalid genome name");
|
|
16
|
+
const ds = g.datasets[q.dslabel];
|
|
17
|
+
if (!ds) throw new Error("Invalid dataset label");
|
|
18
|
+
if (!ds.queries?.singleCell) throw new Error("No single cell data on this dataset");
|
|
19
|
+
return getSingleCellScatter(req, res, ds);
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.error(err);
|
|
22
|
+
res.status(500).json({ error: err.message || String(err) });
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function getSingleCellScatter(req, res, ds) {
|
|
27
|
+
const q = req.query;
|
|
28
|
+
const { name, sample } = q.singleCellPlot;
|
|
29
|
+
try {
|
|
30
|
+
const tw = q.colorTW;
|
|
31
|
+
if (!tw || !isSingleCellTerm(tw.term))
|
|
32
|
+
throw new Error("colorTW must be provided and be a single cell term for single cell scatter plot");
|
|
33
|
+
const arg = { plots: [name], sample };
|
|
34
|
+
if (tw.term.type == SINGLECELL_GENE_EXPRESSION) arg.gene = tw.term.gene;
|
|
35
|
+
else if (tw.term.type == SINGLECELL_CELLTYPE) arg.colorBy = tw.term.name;
|
|
36
|
+
else throw new Error(`unsupported single cell term type: ${tw.term.type}`);
|
|
37
|
+
const data = await ds.queries.singleCell.data.get(arg);
|
|
38
|
+
const plot = data.plots[0];
|
|
39
|
+
const cells = [...plot.expCells, ...plot.noExpCells];
|
|
40
|
+
const groups = tw.q?.customset?.groups;
|
|
41
|
+
const cat2GrpName = /* @__PURE__ */ new Map();
|
|
42
|
+
if (groups) {
|
|
43
|
+
for (const group of groups) {
|
|
44
|
+
for (const value of Object.values(group.values)) {
|
|
45
|
+
cat2GrpName.set(value.key, group.name);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const samples = [];
|
|
50
|
+
const categoryCounts = /* @__PURE__ */ new Map();
|
|
51
|
+
let xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, geMin = Infinity, geMax = -Infinity;
|
|
52
|
+
let totalCellCount = 0;
|
|
53
|
+
for (const cell of cells) {
|
|
54
|
+
let category = cell.category;
|
|
55
|
+
const groupName = cat2GrpName.get(category);
|
|
56
|
+
if (groupName !== void 0) category = groupName;
|
|
57
|
+
const isHidden = tw?.q?.hiddenValues ? category in tw.q.hiddenValues : false;
|
|
58
|
+
totalCellCount++;
|
|
59
|
+
categoryCounts.set(category, (categoryCounts.get(category) || 0) + 1);
|
|
60
|
+
if (cell.x < xMin) xMin = cell.x;
|
|
61
|
+
if (cell.x > xMax) xMax = cell.x;
|
|
62
|
+
if (cell.y < yMin) yMin = cell.y;
|
|
63
|
+
if (cell.y > yMax) yMax = cell.y;
|
|
64
|
+
if (Number.isFinite(cell.geneExp) && cell.geneExp < geMin) geMin = cell.geneExp;
|
|
65
|
+
if (Number.isFinite(cell.geneExp) && cell.geneExp > geMax) geMax = cell.geneExp;
|
|
66
|
+
if (isHidden) continue;
|
|
67
|
+
samples.push({
|
|
68
|
+
sampleId: cell.cellId,
|
|
69
|
+
x: cell.x,
|
|
70
|
+
y: cell.y,
|
|
71
|
+
z: 0,
|
|
72
|
+
category,
|
|
73
|
+
shape: "Ref",
|
|
74
|
+
hidden: { category: false },
|
|
75
|
+
geneExp: cell.geneExp
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const colorMap = {};
|
|
79
|
+
if (tw.term.type == SINGLECELL_CELLTYPE) {
|
|
80
|
+
const defaultK2c = getColors(categoryCounts.size);
|
|
81
|
+
const dsTerm = ds.queries.singleCell?.terms ? ds.queries.singleCell.terms.find((t) => t.name == tw.term.name) : void 0;
|
|
82
|
+
for (const [category, count] of categoryCounts) {
|
|
83
|
+
const color = tw.term.values?.[category]?.color || dsTerm?.values?.[category]?.color || defaultK2c(category);
|
|
84
|
+
colorMap[category] = { sampleCount: count, color, key: category };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const shapeLegend = [["Ref", { sampleCount: totalCellCount, shape: 0, key: "Ref" }]];
|
|
88
|
+
const colorLegend = Object.entries(colorMap);
|
|
89
|
+
const output = {
|
|
90
|
+
range: { xMin, xMax, yMin, yMax, geMin, geMax },
|
|
91
|
+
//There should only be one chart
|
|
92
|
+
result: { Default: { colorLegend, shapeLegend } }
|
|
93
|
+
};
|
|
94
|
+
if (totalCellCount >= q.canvasSettings.cutoff) {
|
|
95
|
+
const { src, canvasWidth, canvasHeight } = await makeCanvas(
|
|
96
|
+
q,
|
|
97
|
+
samples,
|
|
98
|
+
colorMap,
|
|
99
|
+
{ xMin, xMax, yMin, yMax, geMin, geMax },
|
|
100
|
+
tw.term.type
|
|
101
|
+
);
|
|
102
|
+
output.result.Default.src = src;
|
|
103
|
+
output.result.Default.canvasWidth = canvasWidth;
|
|
104
|
+
output.result.Default.canvasHeight = canvasHeight;
|
|
105
|
+
output.result.Default.totalSampleCount = totalCellCount;
|
|
106
|
+
} else {
|
|
107
|
+
output.result.Default.samples = samples;
|
|
108
|
+
}
|
|
109
|
+
res.send(output);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
console.log(e);
|
|
112
|
+
res.send({ error: e.message || e });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function makeCanvas(q, samples, colorMap, range, termType) {
|
|
116
|
+
const settings = q.canvasSettings;
|
|
117
|
+
const dpr = settings.devicePixelRatio || 1;
|
|
118
|
+
const extraSpaceX = calculatePadding(settings.minXScale, settings.maxXScale, range.xMin, range.xMax);
|
|
119
|
+
const extraSpaceY = calculatePadding(settings.minYScale, settings.maxYScale, range.yMin, range.yMax);
|
|
120
|
+
const width = settings.width + xAxisOffSet + extraSpaceX + 20;
|
|
121
|
+
const height = settings.height + yAxisOffSet + extraSpaceY + 20;
|
|
122
|
+
const canvas = createCanvas(width * dpr, height * dpr);
|
|
123
|
+
const ctx = canvas.getContext("2d");
|
|
124
|
+
if (dpr > 1) ctx.scale(dpr, dpr);
|
|
125
|
+
const xScale = scaleLinear().domain([range.xMin - extraSpaceX, range.xMax + extraSpaceX]).range([xAxisOffSet, settings.width + xAxisOffSet]);
|
|
126
|
+
const yScale = scaleLinear().domain([range.yMax + extraSpaceY, range.yMin - extraSpaceY]).range([yAxisOffSet, settings.height + yAxisOffSet]);
|
|
127
|
+
let colorGenerator;
|
|
128
|
+
if (Number.isFinite(range.geMin) && Number.isFinite(range.geMax)) {
|
|
129
|
+
colorGenerator = scaleLinear().domain([range.geMin, range.geMax]).range([settings.startColor, settings.stopColor]);
|
|
130
|
+
}
|
|
131
|
+
const color = (sample) => {
|
|
132
|
+
if (termType == SINGLECELL_GENE_EXPRESSION) {
|
|
133
|
+
if (!Number.isFinite(sample.geneExp)) return settings.startColor;
|
|
134
|
+
else if (sample.geneExp > range.geMax) return settings.stopColor;
|
|
135
|
+
else return colorGenerator(sample.geneExp);
|
|
136
|
+
}
|
|
137
|
+
return colorMap[sample.category] ? colorMap[sample.category].color : refColor;
|
|
138
|
+
};
|
|
139
|
+
const x = (sample) => {
|
|
140
|
+
const tmp = getCoordinate(sample.x, settings.minXScale, settings.maxXScale);
|
|
141
|
+
return xScale(tmp);
|
|
142
|
+
};
|
|
143
|
+
const y = (sample) => {
|
|
144
|
+
const tmp = getCoordinate(sample.y, settings.minYScale, settings.maxYScale);
|
|
145
|
+
return yScale(tmp);
|
|
146
|
+
};
|
|
147
|
+
for (const sample of samples) {
|
|
148
|
+
const c = rgb(color(sample));
|
|
149
|
+
c.opacity = settings.opacity;
|
|
150
|
+
ctx.fillStyle = c.toString();
|
|
151
|
+
ctx.beginPath();
|
|
152
|
+
ctx.arc(x(sample), y(sample), settings.radius, 0, Math.PI * 2);
|
|
153
|
+
ctx.fill();
|
|
154
|
+
}
|
|
155
|
+
return { src: canvas.toDataURL(), canvasWidth: width, canvasHeight: height };
|
|
156
|
+
}
|
|
157
|
+
export {
|
|
158
|
+
init
|
|
159
|
+
};
|
|
@@ -5,24 +5,10 @@ import { mayLog } from "#src/helpers.ts";
|
|
|
5
5
|
import { joinUrl } from "#shared/joinUrl.js";
|
|
6
6
|
import { run_rust } from "@sjcrh/proteinpaint-rust";
|
|
7
7
|
import serverconfig from "#src/serverconfig.js";
|
|
8
|
-
import {
|
|
9
|
-
import { validate_query_singleCell_DEgenes } from "./termdb.singlecellDEgenes.ts";
|
|
8
|
+
import { validate_query_singleCell_DEgenes } from "../src/routes/termdb.singlecellDEgenes.ts";
|
|
10
9
|
import { gdc_validate_query_singleCell_data } from "#src/mds3.gdc.js";
|
|
11
10
|
import ky from "ky";
|
|
12
11
|
import { SINGLECELL_CELLTYPE } from "#shared/terms.js";
|
|
13
|
-
const api = {
|
|
14
|
-
endpoint: "termdb/singlecellSamples",
|
|
15
|
-
methods: {
|
|
16
|
-
get: {
|
|
17
|
-
...termdbSingleCellSamplesPayload,
|
|
18
|
-
init
|
|
19
|
-
},
|
|
20
|
-
post: {
|
|
21
|
-
...termdbSingleCellSamplesPayload,
|
|
22
|
-
init
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
12
|
function init({ genomes }) {
|
|
27
13
|
return async (req, res) => {
|
|
28
14
|
const q = req.query;
|
|
@@ -151,6 +137,10 @@ function validateDataNative(D, ds) {
|
|
|
151
137
|
const plots2 = [];
|
|
152
138
|
for (const plot of D.plots) {
|
|
153
139
|
if (!q.plots.includes(plot.name)) continue;
|
|
140
|
+
if (plot.isMetaResult) {
|
|
141
|
+
const sampleName = plot?.sampleId || plot.name.replace(/\s/g, "_");
|
|
142
|
+
if (sampleName != sampleId) continue;
|
|
143
|
+
}
|
|
154
144
|
const tsvfile = path.join(serverconfig.tpmasterdir, plot.folder, sampleId + (plot.fileSuffix || ""));
|
|
155
145
|
try {
|
|
156
146
|
await file_is_readable(tsvfile);
|
|
@@ -317,6 +307,6 @@ function colorColumn2terms(plots, ds) {
|
|
|
317
307
|
ds.queries.singleCell.terms = [...termSet];
|
|
318
308
|
}
|
|
319
309
|
export {
|
|
320
|
-
|
|
310
|
+
init,
|
|
321
311
|
validate_query_singleCell
|
|
322
312
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { violinBoxPayload } from "#types/checkers";
|
|
2
1
|
import { scaleLinear, scaleLog } from "d3";
|
|
3
2
|
import { run_rust } from "@sjcrh/proteinpaint-rust";
|
|
4
3
|
import { run_R } from "@sjcrh/proteinpaint-r";
|
|
@@ -10,19 +9,6 @@ import { isNumericTerm } from "#shared/terms.js";
|
|
|
10
9
|
import { boxplot_getvalue } from "../src/utils.js";
|
|
11
10
|
import { roundValueAuto } from "#shared/roundValue.js";
|
|
12
11
|
import { mayLog } from "#src/helpers.ts";
|
|
13
|
-
const api = {
|
|
14
|
-
endpoint: "termdb/violinBox",
|
|
15
|
-
methods: {
|
|
16
|
-
get: {
|
|
17
|
-
...violinBoxPayload,
|
|
18
|
-
init
|
|
19
|
-
},
|
|
20
|
-
post: {
|
|
21
|
-
...violinBoxPayload,
|
|
22
|
-
init
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
12
|
function init({ genomes }) {
|
|
27
13
|
return async (req, res) => {
|
|
28
14
|
const q = req.query;
|
|
@@ -535,7 +521,6 @@ function numericBins(tw, data) {
|
|
|
535
521
|
return bins;
|
|
536
522
|
}
|
|
537
523
|
export {
|
|
538
|
-
api,
|
|
539
524
|
buildBins,
|
|
540
525
|
computeSampleType,
|
|
541
526
|
divideValues,
|
|
@@ -544,6 +529,7 @@ export {
|
|
|
544
529
|
getDensities,
|
|
545
530
|
getDensity,
|
|
546
531
|
getViolinWilcoxonData,
|
|
532
|
+
init,
|
|
547
533
|
numericBins,
|
|
548
534
|
parseValues,
|
|
549
535
|
setHiddenPlots,
|
package/routes/wsimages.js
CHANGED
|
@@ -3,25 +3,10 @@ import qs from "qs";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { CookieJar } from "tough-cookie";
|
|
5
5
|
import { promisify } from "util";
|
|
6
|
-
import { wsImagesPayload } from "#types/checkers";
|
|
7
6
|
import SessionManager from "../src/wsisessions/SessionManager.ts";
|
|
8
7
|
import { ShardManager } from "#src/sharding/ShardManager.ts";
|
|
9
8
|
import { TileServerShardingAlgorithm } from "#src/sharding/TileServerShardingAlgorithm.ts";
|
|
10
9
|
import serverconfig from "#src/serverconfig.js";
|
|
11
|
-
const routePath = "wsimages";
|
|
12
|
-
const api = {
|
|
13
|
-
endpoint: `${routePath}`,
|
|
14
|
-
methods: {
|
|
15
|
-
get: {
|
|
16
|
-
...wsImagesPayload,
|
|
17
|
-
init
|
|
18
|
-
},
|
|
19
|
-
post: {
|
|
20
|
-
...wsImagesPayload,
|
|
21
|
-
init
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
10
|
function init({ genomes }) {
|
|
26
11
|
return async (req, res) => {
|
|
27
12
|
try {
|
|
@@ -187,5 +172,5 @@ function getHooks(cookieJar, getCookieString, setCookie) {
|
|
|
187
172
|
};
|
|
188
173
|
}
|
|
189
174
|
export {
|
|
190
|
-
|
|
175
|
+
init
|
|
191
176
|
};
|