@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
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { topMutatedGenePayload } from "#types/checkers";
|
|
2
|
-
import { get_samples } from "#src/termdb.sql.js";
|
|
3
|
-
import { mayLog } from "#src/helpers.ts";
|
|
4
|
-
const api = {
|
|
5
|
-
endpoint: "termdb/topMutatedGenes",
|
|
6
|
-
methods: {
|
|
7
|
-
get: {
|
|
8
|
-
init,
|
|
9
|
-
...topMutatedGenePayload
|
|
10
|
-
},
|
|
11
|
-
post: {
|
|
12
|
-
init,
|
|
13
|
-
...topMutatedGenePayload
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
function init({ genomes }) {
|
|
18
|
-
return async (req, res) => {
|
|
19
|
-
try {
|
|
20
|
-
const q = req.query;
|
|
21
|
-
const g = genomes[q.genome];
|
|
22
|
-
if (!g) throw "genome missing";
|
|
23
|
-
const ds = g.datasets?.[q.dslabel];
|
|
24
|
-
if (!ds) throw "ds missing";
|
|
25
|
-
if (!ds.queries?.topMutatedGenes) throw "not supported by ds";
|
|
26
|
-
const genes = await ds.queries.topMutatedGenes.get(q);
|
|
27
|
-
const payload = { genes };
|
|
28
|
-
res.send(payload);
|
|
29
|
-
} catch (e) {
|
|
30
|
-
res.send({ status: "error", error: e.message || e });
|
|
31
|
-
if (e.stack) console.log(e.stack);
|
|
32
|
-
else console.trace(e);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
function validate_query_getTopMutatedGenes(ds) {
|
|
37
|
-
const q = ds.queries?.topMutatedGenes;
|
|
38
|
-
if (!q) return;
|
|
39
|
-
if (typeof q.get == "function") return;
|
|
40
|
-
if (!q.arguments) {
|
|
41
|
-
q.arguments = [];
|
|
42
|
-
q.arguments.push({ id: "maxGenes", label: "Gene Count", type: "number", value: 50 });
|
|
43
|
-
if (ds.queries.snvindel) {
|
|
44
|
-
q.arguments.push({ id: "snv_mfndi", label: "Protein-changing mutation", type: "boolean", value: true });
|
|
45
|
-
q.arguments.push({ id: "snv_splice", label: "Splice mutation", type: "boolean", value: true });
|
|
46
|
-
q.arguments.push({ id: "snv_utr", label: "UTR mutation", type: "boolean", value: true });
|
|
47
|
-
q.arguments.push({ id: "snv_s", label: "Silent mutation", type: "boolean", value: true });
|
|
48
|
-
}
|
|
49
|
-
if (ds.queries.svfusion) {
|
|
50
|
-
q.arguments.push({ id: "sv", label: "Structural variation", type: "boolean", value: true });
|
|
51
|
-
q.arguments.push({ id: "fusion", label: "RNA fusion", type: "boolean", value: true });
|
|
52
|
-
}
|
|
53
|
-
if (ds.queries.cnv) {
|
|
54
|
-
q.arguments.push({
|
|
55
|
-
id: "cnv",
|
|
56
|
-
type: "boolean",
|
|
57
|
-
label: "CNV",
|
|
58
|
-
checked: false,
|
|
59
|
-
noStyle: true,
|
|
60
|
-
//This is a hack
|
|
61
|
-
options: [
|
|
62
|
-
{
|
|
63
|
-
id: "cnv_ms",
|
|
64
|
-
label: "Max size",
|
|
65
|
-
type: "radio",
|
|
66
|
-
options: [
|
|
67
|
-
{ id: "cnv_1mb", label: "<1Mb", value: "cnv_1mb" },
|
|
68
|
-
{ id: "cnv_2mb", label: "<2Mb", value: "cnv_2mb" },
|
|
69
|
-
{ id: "cnv_4mb", label: "<4Mb", value: "cnv_4mb" }
|
|
70
|
-
]
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
id: "cnv_logratio",
|
|
74
|
-
label: "Min absolute log(ratio)",
|
|
75
|
-
type: "radio",
|
|
76
|
-
options: [
|
|
77
|
-
{ id: "_01", label: ">0.1", value: "_01" },
|
|
78
|
-
{ id: "_02", label: ">0.2", value: "_02" },
|
|
79
|
-
{ id: "_03", label: ">0.3", value: "_03" }
|
|
80
|
-
]
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
q.get = async (param) => {
|
|
87
|
-
let sampleStatement = "";
|
|
88
|
-
if (param.filter) {
|
|
89
|
-
const lst = await get_samples(param, ds);
|
|
90
|
-
if (lst.length == 0) throw "empty sample filter";
|
|
91
|
-
sampleStatement = `WHERE sample IN (${lst.map((i) => i.id).join(",")})`;
|
|
92
|
-
}
|
|
93
|
-
const fields = [];
|
|
94
|
-
if (param.snv_mfndi) fields.push("snv_mfndi");
|
|
95
|
-
if (param.snv_splice) fields.push("snv_splice");
|
|
96
|
-
if (param.snv_utr) fields.push("snv_utr");
|
|
97
|
-
if (param.snv_s) fields.push("snv_s");
|
|
98
|
-
if (param.sv) fields.push("sv");
|
|
99
|
-
if (param.fusion) fields.push("fusion");
|
|
100
|
-
if (param.cnv == 1 && param.cnv_ms?.type && param.cnv_logratio?.type) {
|
|
101
|
-
fields.push(param.cnv_ms.type + param.cnv_logratio.type);
|
|
102
|
-
}
|
|
103
|
-
if (!fields.length) throw "no fields";
|
|
104
|
-
const query = `WITH
|
|
105
|
-
filtered AS (
|
|
106
|
-
SELECT genesymbol, ${fields.join("+")} AS total FROM genesamplemutationcount
|
|
107
|
-
${sampleStatement}
|
|
108
|
-
)
|
|
109
|
-
SELECT genesymbol, SUM(total) AS count
|
|
110
|
-
FROM filtered
|
|
111
|
-
GROUP BY genesymbol
|
|
112
|
-
ORDER BY count DESC
|
|
113
|
-
LIMIT ${param.maxGenes || 20}`;
|
|
114
|
-
const t = Date.now();
|
|
115
|
-
const genes = ds.cohort.db.connection.prepare(query).all();
|
|
116
|
-
mayLog("Top mutated gene sql", Date.now() - t, "ms");
|
|
117
|
-
const results = [];
|
|
118
|
-
for (const g of genes) {
|
|
119
|
-
results.push({ gene: g.genesymbol });
|
|
120
|
-
}
|
|
121
|
-
return results;
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
export {
|
|
125
|
-
api,
|
|
126
|
-
validate_query_getTopMutatedGenes
|
|
127
|
-
};
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { termdbTopTermsByTypePayload } from "#types/checkers";
|
|
2
|
-
import { run_rust } from "@sjcrh/proteinpaint-rust";
|
|
3
|
-
import { get_samples } from "#src/termdb.sql.js";
|
|
4
|
-
import { TermTypes } from "#shared/terms.js";
|
|
5
|
-
const api = {
|
|
6
|
-
endpoint: "termdb/getTopTermsByType",
|
|
7
|
-
methods: {
|
|
8
|
-
get: {
|
|
9
|
-
...termdbTopTermsByTypePayload,
|
|
10
|
-
init
|
|
11
|
-
},
|
|
12
|
-
post: {
|
|
13
|
-
...termdbTopTermsByTypePayload,
|
|
14
|
-
init
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
function init({ genomes }) {
|
|
19
|
-
return async (req, res) => {
|
|
20
|
-
try {
|
|
21
|
-
const q = req.query;
|
|
22
|
-
const type = q.type;
|
|
23
|
-
const genome = genomes[q.genome];
|
|
24
|
-
if (!genome) throw "invalid genome";
|
|
25
|
-
const ds = genome.datasets?.[q.dslabel];
|
|
26
|
-
if (!ds) throw "invalid dslabel";
|
|
27
|
-
if (!ds.queries[type]) throw "not supported on dataset";
|
|
28
|
-
const terms = await ds.queries[type].getTopTerms(q);
|
|
29
|
-
res.send({ terms });
|
|
30
|
-
} catch (e) {
|
|
31
|
-
res.send({ status: "error", error: e.message || e });
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
function validate_query_getTopTermsByType(ds, genome) {
|
|
36
|
-
const types = [TermTypes.METABOLITE_INTENSITY];
|
|
37
|
-
for (const type of types) {
|
|
38
|
-
if (ds.queries[type]) {
|
|
39
|
-
const q = ds.queries[type];
|
|
40
|
-
if (!q) return;
|
|
41
|
-
if (q.src == "gdcapi") gdcValidateQuery(ds, genome, type);
|
|
42
|
-
else if (q.src == "native") nativeValidateQuery(ds, type);
|
|
43
|
-
else throw "unknown topVariablyExpressedGenes.src";
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function nativeValidateQuery(ds, type) {
|
|
48
|
-
ds.queries[type].getTopTerms = async (q) => {
|
|
49
|
-
const typeQuery = ds.queries[type];
|
|
50
|
-
const samples = [];
|
|
51
|
-
if (q.filter) {
|
|
52
|
-
const sidlst = await get_samples(q, ds);
|
|
53
|
-
for (const i of sidlst) {
|
|
54
|
-
if (typeQuery.samples.includes(i.id)) {
|
|
55
|
-
const n = ds.cohort.termdb.q.id2sampleName(i.id);
|
|
56
|
-
if (!n) throw "sample id cannot convert to string name";
|
|
57
|
-
samples.push(n);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
} else {
|
|
61
|
-
for (const i of typeQuery.samples) {
|
|
62
|
-
const n = ds.cohort.termdb.q.id2sampleName(i.id);
|
|
63
|
-
if (!n) throw "sample id cannot convert to string name";
|
|
64
|
-
samples.push(n);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const terms = await computeTopTerms(typeQuery.file, samples, type);
|
|
68
|
-
return terms;
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
async function computeTopTerms(file, samples, type) {
|
|
72
|
-
const input_json = {
|
|
73
|
-
input_file: file,
|
|
74
|
-
samples: samples.join(","),
|
|
75
|
-
param: "var"
|
|
76
|
-
};
|
|
77
|
-
const rust_result = await run_rust("computeTopTerms", JSON.stringify(input_json));
|
|
78
|
-
const rust_result_list = rust_result.split("\n");
|
|
79
|
-
let output_json;
|
|
80
|
-
for (const item of rust_result_list) {
|
|
81
|
-
if (item.includes("output_json")) {
|
|
82
|
-
output_json = JSON.parse(item.replace("output_json:", ""));
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
const varMetabolite = output_json.map((i) => ({ name: i.metabolite, type }));
|
|
86
|
-
return varMetabolite;
|
|
87
|
-
}
|
|
88
|
-
function gdcValidateQuery(ds, genome, type) {
|
|
89
|
-
ds.queries[type].getTopTerms = async () => {
|
|
90
|
-
return [];
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
export {
|
|
94
|
-
api,
|
|
95
|
-
validate_query_getTopTermsByType
|
|
96
|
-
};
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { termdbTopVariablyExpressedGenesPayload } from "#types/checkers";
|
|
2
|
-
import { mayLimitSamples } from "#src/mds3.filter.js";
|
|
3
|
-
import { run_python } from "@sjcrh/proteinpaint-python";
|
|
4
|
-
import { mayLog } from "#src/helpers.ts";
|
|
5
|
-
const api = {
|
|
6
|
-
endpoint: "termdb/topVariablyExpressedGenes",
|
|
7
|
-
methods: {
|
|
8
|
-
get: {
|
|
9
|
-
...termdbTopVariablyExpressedGenesPayload,
|
|
10
|
-
init
|
|
11
|
-
},
|
|
12
|
-
post: {
|
|
13
|
-
...termdbTopVariablyExpressedGenesPayload,
|
|
14
|
-
init
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
function init({ genomes }) {
|
|
19
|
-
return async (req, res) => {
|
|
20
|
-
let result;
|
|
21
|
-
try {
|
|
22
|
-
const q = req.query;
|
|
23
|
-
const genome = genomes[q.genome];
|
|
24
|
-
if (!genome) throw "invalid genome";
|
|
25
|
-
const ds = genome.datasets?.[q.dslabel];
|
|
26
|
-
if (!ds) throw "invalid dslabel";
|
|
27
|
-
if (!ds.queries?.topVariablyExpressedGenes) throw "not supported on dataset";
|
|
28
|
-
q.ds = ds;
|
|
29
|
-
const t = Date.now();
|
|
30
|
-
result = {
|
|
31
|
-
genes: await ds.queries.topVariablyExpressedGenes.getGenes(q)
|
|
32
|
-
};
|
|
33
|
-
mayLog("time for top variably expressed genes", Date.now() - t);
|
|
34
|
-
} catch (e) {
|
|
35
|
-
result = { status: e.status || 400, error: e.message || e };
|
|
36
|
-
}
|
|
37
|
-
res.send(result);
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
function validate_query_TopVariablyExpressedGenes(ds) {
|
|
41
|
-
const q = ds.queries.topVariablyExpressedGenes;
|
|
42
|
-
if (!q) return;
|
|
43
|
-
if (typeof q.getGenes == "function") return;
|
|
44
|
-
nativeValidateQuery(ds);
|
|
45
|
-
}
|
|
46
|
-
function nativeValidateQuery(ds) {
|
|
47
|
-
const gE = ds.queries.geneExpression;
|
|
48
|
-
if (!gE) throw "topVariablyExpressedGenes query given but geneExpression missing";
|
|
49
|
-
if (gE.src != "native") throw "topVariablyExpressedGenes is native but geneExpression.src is not native";
|
|
50
|
-
addTopVEarg(ds.queries.topVariablyExpressedGenes);
|
|
51
|
-
ds.queries.topVariablyExpressedGenes.getGenes = async (q) => {
|
|
52
|
-
const samples = [];
|
|
53
|
-
const param = { filter: q.filter, filter0: q.filter0 };
|
|
54
|
-
const limitSamples = await mayLimitSamples(param, gE.samples, ds);
|
|
55
|
-
if (limitSamples) {
|
|
56
|
-
for (const sid of limitSamples) {
|
|
57
|
-
const n = ds.cohort.termdb.q.id2sampleName(sid);
|
|
58
|
-
if (!n) throw "sample id cannot convert to string name";
|
|
59
|
-
samples.push(n);
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
for (const i of gE.samples) {
|
|
63
|
-
const n = ds.cohort.termdb.q.id2sampleName(i);
|
|
64
|
-
if (!n) throw "sample id cannot convert to string name";
|
|
65
|
-
samples.push(n);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return await computeGenes4nativeDs(q, gE, samples);
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
function addTopVEarg(q) {
|
|
72
|
-
const arglst = [
|
|
73
|
-
{ id: "maxGenes", label: "Gene Count", type: "number", value: 100 },
|
|
74
|
-
{
|
|
75
|
-
id: "filter_extreme_values",
|
|
76
|
-
label: "Filter Extreme Values",
|
|
77
|
-
type: "boolean",
|
|
78
|
-
value: true
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
id: "rank_type",
|
|
82
|
-
label: "Rank by:",
|
|
83
|
-
type: "radio",
|
|
84
|
-
options: [
|
|
85
|
-
/** The param option in input JSON is very important.
|
|
86
|
-
* It instructs what method will be used to calculate variation in the counts for a particular gene.
|
|
87
|
-
* It supports variance as well as interquartile region.
|
|
88
|
-
* This is based on the recommendation of this article:
|
|
89
|
-
* https://www.frontiersin.org/articles/10.3389/fgene.2021.632620/full.
|
|
90
|
-
* This article recommends using interquartile region over variance.*/
|
|
91
|
-
{
|
|
92
|
-
type: "boolean",
|
|
93
|
-
label: "Variance",
|
|
94
|
-
value: "var"
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
type: "boolean",
|
|
98
|
-
label: "Interquartile Region",
|
|
99
|
-
value: "iqr"
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
];
|
|
104
|
-
if (q.arguments) {
|
|
105
|
-
for (const a of q.arguments) {
|
|
106
|
-
if (!a.id) throw "missing id of topVE.arguments[]";
|
|
107
|
-
const item = arglst.find((i) => i.id == a.id);
|
|
108
|
-
if (!item) throw "unknown id of topVE.arguments[]";
|
|
109
|
-
Object.assign(item, a);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
q.arguments = arglst;
|
|
113
|
-
}
|
|
114
|
-
async function computeGenes4nativeDs(q, gE, samples) {
|
|
115
|
-
if (!["number", "boolean"].includes(typeof q.filter_extreme_values) || q.filter_extreme_values === void 0) {
|
|
116
|
-
q.filter_extreme_values = false;
|
|
117
|
-
}
|
|
118
|
-
const input_json = {
|
|
119
|
-
input_file: gE.file,
|
|
120
|
-
samples: samples.join(","),
|
|
121
|
-
filter_extreme_values: typeof q.filter_extreme_values === "number" ? Boolean(q.filter_extreme_values) : q.filter_extreme_values,
|
|
122
|
-
max_genes: q.maxGenes,
|
|
123
|
-
rank_type: q.rank_type?.type ?? "var"
|
|
124
|
-
};
|
|
125
|
-
const python_output = await run_python("topVEgene.py", JSON.stringify(input_json));
|
|
126
|
-
const varGenes = typeof python_output === "string" ? JSON.parse(python_output) : [];
|
|
127
|
-
return varGenes;
|
|
128
|
-
}
|
|
129
|
-
export {
|
|
130
|
-
api,
|
|
131
|
-
validate_query_TopVariablyExpressedGenes
|
|
132
|
-
};
|
package/routes/tileserver.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { tilePayload } from "#types/checkers";
|
|
2
|
-
import ky from "ky";
|
|
3
|
-
import { TileServerShardingAlgorithm } from "#src/sharding/TileServerShardingAlgorithm.ts";
|
|
4
|
-
import { ShardManager } from "#src/sharding/ShardManager.ts";
|
|
5
|
-
import SessionManager from "#src/wsisessions/SessionManager.ts";
|
|
6
|
-
import serverconfig from "#src/serverconfig.js";
|
|
7
|
-
import path from "path";
|
|
8
|
-
const api = {
|
|
9
|
-
endpoint: `tileserver/layer/:type/:sessionId/zoomify/:TileGroup/:z-:x-:y@1x.jpg`,
|
|
10
|
-
methods: {
|
|
11
|
-
get: {
|
|
12
|
-
...tilePayload,
|
|
13
|
-
init
|
|
14
|
-
},
|
|
15
|
-
post: {
|
|
16
|
-
...tilePayload,
|
|
17
|
-
init
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
function init({ genomes }) {
|
|
22
|
-
return async (req, res) => {
|
|
23
|
-
try {
|
|
24
|
-
const { type, sessionId, TileGroup, z, x, y } = req.params;
|
|
25
|
-
const query = req.query;
|
|
26
|
-
const wsiImage = query.wsi_image;
|
|
27
|
-
if (!wsiImage) throw new Error("No wsi_image param provided");
|
|
28
|
-
const dslabel = query.dslabel;
|
|
29
|
-
if (!dslabel) throw new Error("No dslabel param provided");
|
|
30
|
-
const g = genomes[query.genome];
|
|
31
|
-
if (!g) throw new Error("Invalid genome name");
|
|
32
|
-
const ds = g.datasets[query.dslabel];
|
|
33
|
-
if (!ds) throw new Error("Invalid dataset name");
|
|
34
|
-
const sampleId = query.sample_id;
|
|
35
|
-
const projectId = query.ai_project_id;
|
|
36
|
-
if (!sampleId && !projectId) throw new Error("Either sample_id or project_id must be provided");
|
|
37
|
-
const mount = serverconfig.features?.tileserver?.mount;
|
|
38
|
-
if (!mount) throw new Error("No mount available for TileServer");
|
|
39
|
-
let wsiImagePath;
|
|
40
|
-
if (sampleId) {
|
|
41
|
-
wsiImagePath = path.join(`${mount}/${ds.queries.WSImages.imageBySampleFolder}/${sampleId}`, wsiImage);
|
|
42
|
-
} else {
|
|
43
|
-
wsiImagePath = path.join(`${mount}/${ds.queries.WSImages.aiToolImageFolder}/`, wsiImage);
|
|
44
|
-
}
|
|
45
|
-
if (!wsiImage) throw new Error("Invalid wsi_image");
|
|
46
|
-
const shardManager = ShardManager.getInstance();
|
|
47
|
-
const tileServer = await shardManager.shardingAlgorithmsMap?.get(TileServerShardingAlgorithm.TILE_SERVER_SHARDING_KEY)?.getShard(wsiImagePath);
|
|
48
|
-
if (!tileServer) {
|
|
49
|
-
throw new Error("No tile server");
|
|
50
|
-
}
|
|
51
|
-
const url = `${tileServer.url}/tileserver/layer/${type}/${sessionId}/zoomify/${TileGroup}/${z}-${x}-${y}@1x.jpg`;
|
|
52
|
-
const response = await ky.get(url, { timeout: 12e4 });
|
|
53
|
-
await SessionManager.getInstance().updateSession(wsiImagePath);
|
|
54
|
-
const buffer = await response.arrayBuffer();
|
|
55
|
-
res.status(response.status).send(Buffer.from(buffer));
|
|
56
|
-
} catch (error) {
|
|
57
|
-
if (error.response) {
|
|
58
|
-
const errorBody = await error.response.arrayBuffer();
|
|
59
|
-
res.status(error.response.status).send(Buffer.from(errorBody));
|
|
60
|
-
} else {
|
|
61
|
-
res.status(500).send("Internal Server Error");
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
export {
|
|
67
|
-
api
|
|
68
|
-
};
|
package/routes/wsisamples.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { wsiSamplesPayload } from "#types/checkers";
|
|
2
|
-
const routePath = "wsisamples";
|
|
3
|
-
const api = {
|
|
4
|
-
endpoint: `${routePath}`,
|
|
5
|
-
methods: {
|
|
6
|
-
get: {
|
|
7
|
-
...wsiSamplesPayload,
|
|
8
|
-
init
|
|
9
|
-
},
|
|
10
|
-
post: {
|
|
11
|
-
...wsiSamplesPayload,
|
|
12
|
-
init
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
function init({ genomes }) {
|
|
17
|
-
return async (req, res) => {
|
|
18
|
-
try {
|
|
19
|
-
const query = req.query;
|
|
20
|
-
const g = genomes[query.genome];
|
|
21
|
-
if (!g) throw new Error("Invalid genome name");
|
|
22
|
-
const ds = g.datasets[query.dslabel];
|
|
23
|
-
if (!ds) throw "Invalid dslabel";
|
|
24
|
-
const images = await ds.queries.WSImages.getSamples();
|
|
25
|
-
const payload = {
|
|
26
|
-
samples: images
|
|
27
|
-
};
|
|
28
|
-
res.status(200).json(payload);
|
|
29
|
-
} catch (e) {
|
|
30
|
-
console.warn(e);
|
|
31
|
-
res.status(500).send({
|
|
32
|
-
status: "error",
|
|
33
|
-
error: e.message || e
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
async function validate_query_getWSISamples(ds) {
|
|
39
|
-
const q = ds.queries?.WSImages;
|
|
40
|
-
if (!q) return;
|
|
41
|
-
validateQuery(ds);
|
|
42
|
-
}
|
|
43
|
-
function validateQuery(ds) {
|
|
44
|
-
if (typeof ds.queries.WSImages.getSamples == "function") {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
ds.queries.WSImages.getSamples = async () => {
|
|
48
|
-
const sql = `SELECT wsimages.sample as sample, wsimages.filename as filename, wsimages.metadata as metadata, sampleidmap.name as sampleName
|
|
49
|
-
FROM wsimages
|
|
50
|
-
INNER JOIN sampleidmap
|
|
51
|
-
ON wsimages.sample = sampleidmap.id`;
|
|
52
|
-
try {
|
|
53
|
-
const rows = ds.cohort.db.connection.prepare(sql).all();
|
|
54
|
-
const sampleMap = {};
|
|
55
|
-
for (const row of rows) {
|
|
56
|
-
if (!sampleMap[row.sample]) {
|
|
57
|
-
sampleMap[row.sample] = { sampleId: row.sampleName, wsimages: [] };
|
|
58
|
-
}
|
|
59
|
-
sampleMap[row.sample].wsimages.push(row.filename);
|
|
60
|
-
}
|
|
61
|
-
return Object.values(sampleMap);
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.error("Error fetching samples:", error);
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
export {
|
|
69
|
-
api,
|
|
70
|
-
validate_query_getWSISamples
|
|
71
|
-
};
|