@sjcrh/proteinpaint-server 2.189.0 → 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.
Files changed (82) hide show
  1. package/package.json +9 -12
  2. package/routes/aiProjectAdmin.js +2 -28
  3. package/routes/aiProjectSelectedWSImages.js +2 -16
  4. package/routes/brainImaging.js +1 -15
  5. package/routes/brainImagingSamples.js +1 -15
  6. package/routes/burden.js +1 -15
  7. package/routes/correlationVolcano.js +1 -15
  8. package/routes/dataset.js +1 -16
  9. package/routes/deleteWSITileSelection.js +2 -12
  10. package/routes/dsdata.js +1 -19
  11. package/routes/gdc.grin2.list.js +1 -15
  12. package/routes/gdc.grin2.run.js +1 -15
  13. package/routes/gdc.maf.js +1 -15
  14. package/routes/gdc.mafBuild.js +1 -15
  15. package/routes/genesetEnrichment.js +129 -97
  16. package/routes/grin2.js +110 -79
  17. package/routes/saveWSIAnnotation.js +2 -13
  18. package/routes/termdb.DE.js +137 -54
  19. package/routes/termdb.categories.js +2 -16
  20. package/routes/termdb.chat.js +169 -1076
  21. package/routes/termdb.cluster.js +5 -16
  22. package/routes/termdb.config.js +12 -17
  23. package/routes/termdb.descrstats.js +2 -16
  24. package/routes/termdb.diffMeth.js +100 -21
  25. package/routes/termdb.geneRanking.js +139 -0
  26. package/routes/termdb.proteome.js +1 -15
  27. package/routes/termdb.runChart.js +16 -30
  28. package/routes/termdb.sampleScatter.js +7 -97
  29. package/routes/termdb.singleCellPlots.js +159 -0
  30. package/routes/termdb.singlecellSamples.js +6 -16
  31. package/routes/termdb.violinBox.js +1 -15
  32. package/routes/wsimages.js +1 -16
  33. package/src/app.js +3984 -4103
  34. package/routes/_template_.js +0 -33
  35. package/routes/aiProjectTrainModel.js +0 -68
  36. package/routes/alphaGenome.js +0 -41
  37. package/routes/alphaGenomeTypes.js +0 -36
  38. package/routes/dzimages.js +0 -55
  39. package/routes/gene2canonicalisoform.js +0 -37
  40. package/routes/genelookup.js +0 -32
  41. package/routes/genesetOverrepresentation.js +0 -49
  42. package/routes/genomes.js +0 -150
  43. package/routes/healthcheck.js +0 -35
  44. package/routes/hicdata.js +0 -74
  45. package/routes/hicgenome.js +0 -75
  46. package/routes/hicstat.js +0 -35
  47. package/routes/img.js +0 -46
  48. package/routes/isoformlst.js +0 -48
  49. package/routes/ntseq.js +0 -36
  50. package/routes/pdomain.js +0 -53
  51. package/routes/profile.barchart2.js +0 -114
  52. package/routes/profile.forms2.js +0 -107
  53. package/routes/profile.polar2.js +0 -101
  54. package/routes/profile.radar2.js +0 -112
  55. package/routes/profile.radarFacility2.js +0 -148
  56. package/routes/sampledzimages.js +0 -48
  57. package/routes/samplewsimages.js +0 -60
  58. package/routes/snp.js +0 -98
  59. package/routes/termdb.chat2.js +0 -217
  60. package/routes/termdb.chat3.js +0 -209
  61. package/routes/termdb.cohort.summary.js +0 -37
  62. package/routes/termdb.cohorts.js +0 -41
  63. package/routes/termdb.dapVolcano.js +0 -80
  64. package/routes/termdb.dmr.js +0 -93
  65. package/routes/termdb.filterTermValues.js +0 -89
  66. package/routes/termdb.isoformAvailability.js +0 -35
  67. package/routes/termdb.numericcategories.js +0 -46
  68. package/routes/termdb.percentile.js +0 -66
  69. package/routes/termdb.profileFormScores.js +0 -92
  70. package/routes/termdb.profileScores.js +0 -113
  71. package/routes/termdb.rootterm.js +0 -39
  72. package/routes/termdb.sampleImages.js +0 -63
  73. package/routes/termdb.singleSampleMutation.js +0 -75
  74. package/routes/termdb.singlecellDEgenes.js +0 -55
  75. package/routes/termdb.singlecellData.js +0 -39
  76. package/routes/termdb.termchildren.js +0 -42
  77. package/routes/termdb.termsbyids.js +0 -50
  78. package/routes/termdb.topMutatedGenes.js +0 -127
  79. package/routes/termdb.topTermsByType.js +0 -96
  80. package/routes/termdb.topVariablyExpressedGenes.js +0 -132
  81. package/routes/tileserver.js +0 -68
  82. 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
- };
@@ -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
- };
@@ -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
- };