@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.
Files changed (82) hide show
  1. package/package.json +9 -12
  2. package/routes/aiProjectAdmin.js +2 -28
  3. package/routes/aiProjectSelectedWSImages.js +2 -17
  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 +4014 -4127
  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,209 +0,0 @@
1
- import { ChatPayload } from "#types/checkers";
2
- import { mayLog } from "#src/helpers.ts";
3
- import { formatElapsedTime } from "#shared";
4
- import { readJSONFile, parse_geneset_db, getChatRelatedPlotTypes } from "./chat/utils.ts";
5
- import { classifyQuery } from "./chat/classify1.ts";
6
- import { classifyPlotType } from "./chat/plot.ts";
7
- import { classifyNotPlot } from "./chat/classify2.ts";
8
- import { inferScaffold } from "./chat/scaffold.ts";
9
- import serverconfig from "../src/serverconfig.js";
10
- import { getDsAllowedTermTypes } from "./termdb.config.ts";
11
- import { phrase2entity } from "./chat/phrase2entity.ts";
12
- import { inferTermObjFromEntity } from "./chat/entity2termObj.ts";
13
- import { resolveToTwTvs } from "./chat/entity2twTvs.ts";
14
- import { answerDataQueries } from "./chat/dataQueries.ts";
15
- import path from "path";
16
- import fs from "fs";
17
- import { resolveToPlotState } from "./chat/scaffold2state.ts";
18
- const api = {
19
- endpoint: "termdb/chat3",
20
- methods: {
21
- get: {
22
- ...ChatPayload,
23
- init
24
- },
25
- post: {
26
- ...ChatPayload,
27
- init
28
- }
29
- }
30
- };
31
- function init({ genomes }) {
32
- return async (req, res) => {
33
- const q = req.query;
34
- try {
35
- const genome = genomes[q.genome];
36
- if (!genome) throw "invalid genome";
37
- const ds = genome.datasets?.[q.dslabel];
38
- if (!ds) throw "invalid dslabel";
39
- const aiFilesDir = serverconfig.binpath + "/../../dataset/ai/" + q.dslabel;
40
- let agentFiles = [];
41
- try {
42
- agentFiles = await fs.readdirSync(aiFilesDir).filter((file) => file.endsWith(".json"));
43
- } catch (err) {
44
- if (err.code === "ENOENT") throw new Error(`Directory not found: ${aiFilesDir}`);
45
- if (err.code === "ENOTDIR") throw new Error(`Path is not a directory: ${aiFilesDir}`);
46
- throw err;
47
- }
48
- const llm = serverconfig.llm;
49
- if (!llm) throw "serverconfig.llm is not configured";
50
- if (llm.provider !== "SJ" && llm.provider !== "ollama" && llm.provider !== "huggingface" && llm.provider !== "azure") {
51
- throw "llm.provider must be 'SJ', 'ollama', 'huggingface', or 'azure'";
52
- }
53
- let rawFilter;
54
- if (typeof q.filter === "string") {
55
- try {
56
- rawFilter = JSON.parse(q.filter);
57
- } catch (e) {
58
- throw new Error("Failed to parse filter JSON string: " + e);
59
- }
60
- } else {
61
- rawFilter = q.filter;
62
- }
63
- const filter = rawFilter && typeof rawFilter === "object" ? rawFilter : {};
64
- const lst = Array.isArray(filter.lst) ? filter.lst : [];
65
- const cohortFilter = lst.find((item) => item.tag === "cohortFilter");
66
- const cohortKey = cohortFilter ? cohortFilter.tvs.values[0].key : "";
67
- const supportedPlotTypes = ds.cohort.termdb.q?.getSupportedChartTypes(req)?.[cohortKey];
68
- const chatSupportedPlotTypes = getChatRelatedPlotTypes(supportedPlotTypes);
69
- const genedb = serverconfig.tpmasterdir + "/" + genome.genedb.dbfile;
70
- const allowedTermTypes = getDsAllowedTermTypes(ds);
71
- const ai_output_json = await run_chat_pipeline(
72
- q.prompt,
73
- llm,
74
- ds,
75
- genedb,
76
- agentFiles,
77
- aiFilesDir,
78
- chatSupportedPlotTypes,
79
- allowedTermTypes,
80
- genome
81
- // testing
82
- );
83
- mayLog("From init: Final AI output JSON:", JSON.stringify(ai_output_json));
84
- res.send(ai_output_json);
85
- } catch (e) {
86
- if (e.stack) mayLog(e.stack);
87
- res.send({ error: e?.message || e });
88
- }
89
- };
90
- }
91
- async function run_chat_pipeline(userPrompt, llm, ds, genedb, agentFiles, aiFilesDir, supportedPlotTypes, allowedTermTypes, genome) {
92
- if (!fs.existsSync(path.join(aiFilesDir, "main.json")))
93
- throw "Main data file is not specified for dataset:" + ds.label;
94
- const dataset_json = await readJSONFile(path.join(aiFilesDir, "main.json"));
95
- const time1 = (/* @__PURE__ */ new Date()).valueOf();
96
- const class_response = await classifyQuery(userPrompt, llm);
97
- mayLog("Time taken for classification:", formatElapsedTime(Date.now() - time1));
98
- let ai_output_json;
99
- if (class_response.type === "notplot") {
100
- const time2 = (/* @__PURE__ */ new Date()).valueOf();
101
- const notPlotResult = await classifyNotPlot(userPrompt, llm, agentFiles, aiFilesDir);
102
- mayLog("Time taken for classify2:", formatElapsedTime(Date.now() - time2));
103
- if (notPlotResult.type === "html") {
104
- ai_output_json = notPlotResult;
105
- } else {
106
- ai_output_json = {
107
- type: "text",
108
- text: "Your query does not appear to be related to the available data visualizations. Please try rephrasing your question."
109
- };
110
- }
111
- } else if (class_response.type === "binaryQuery") {
112
- const answer = await answerDataQueries(userPrompt, llm, allowedTermTypes);
113
- if (!answer) throw "Couldn't decide if this is data related query!";
114
- mayLog("Data Binary Query: ", answer);
115
- ai_output_json = answer;
116
- } else if (class_response.type === "plot") {
117
- let time = (/* @__PURE__ */ new Date()).valueOf();
118
- const plotType = await classifyPlotType(userPrompt, llm);
119
- mayLog("Time taken to classify plot type:", formatElapsedTime(Date.now() - time));
120
- if (!supportedPlotTypes.includes(plotType)) {
121
- const log = 'Plot type: "' + plotType + '" is not supported.';
122
- ai_output_json = {
123
- type: "text",
124
- text: log
125
- };
126
- mayLog(log);
127
- return ai_output_json;
128
- }
129
- const genes_list = await parse_geneset_db(genedb);
130
- mayLog("#################################################");
131
- mayLog("####### First phase: Infer Plot Scaffolds #######");
132
- mayLog("#################################################");
133
- time = (/* @__PURE__ */ new Date()).valueOf();
134
- const dataset_db = serverconfig.tpmasterdir + "/" + ds.cohort.db.file;
135
- const scaffoldResult = await inferScaffold(
136
- userPrompt,
137
- plotType,
138
- llm,
139
- genome,
140
- genes_list,
141
- allowedTermTypes,
142
- dataset_json,
143
- ds,
144
- dataset_db
145
- );
146
- mayLog("ScaffoldResult: ", scaffoldResult);
147
- if (plotType === "hiercluster" && "plot" in scaffoldResult && scaffoldResult.type === "plot" || "text" in scaffoldResult && scaffoldResult.type === "text") {
148
- return scaffoldResult;
149
- }
150
- mayLog("Time taken to infer scaffold:", formatElapsedTime(Date.now() - time));
151
- if (!scaffoldResult)
152
- throw "Scaffold result is empty or undefined, which is unexpected. Please check the inferScaffold agent for potential issues.";
153
- if ("type" in scaffoldResult && scaffoldResult.type === "text") {
154
- return scaffoldResult;
155
- }
156
- const subplotType = scaffoldResult.plotType === "summary" ? scaffoldResult.chartType : void 0;
157
- mayLog("#################################################");
158
- mayLog("####### Second phase: From Scaffolds's phrases infer Entities #######");
159
- mayLog("#################################################");
160
- time = (/* @__PURE__ */ new Date()).valueOf();
161
- const phrase2entityResult = await phrase2entity(
162
- scaffoldResult,
163
- plotType,
164
- llm,
165
- genes_list,
166
- dataset_json,
167
- ds
168
- );
169
- mayLog("Time taken to phrase 2 entity:", formatElapsedTime(Date.now() - time));
170
- if ("type" in phrase2entityResult && phrase2entityResult.type === "text") {
171
- return phrase2entityResult;
172
- }
173
- mayLog(phrase2entityResult);
174
- mayLog("#################################################");
175
- mayLog("####### Third phase: From Entities infer Term Objects #######");
176
- mayLog("#################################################");
177
- time = (/* @__PURE__ */ new Date()).valueOf();
178
- const termObj = await inferTermObjFromEntity(
179
- phrase2entityResult,
180
- plotType,
181
- llm,
182
- dataset_db,
183
- genes_list
184
- );
185
- mayLog("Time taken to infer term objects:", formatElapsedTime(Date.now() - time));
186
- mayLog("Inferred termObj from entity:", JSON.stringify(termObj));
187
- mayLog("#################################################");
188
- mayLog("####### Fourth phase: From Term Objects to TwTvs Objects #######");
189
- mayLog("#################################################");
190
- time = (/* @__PURE__ */ new Date()).valueOf();
191
- const twTvsObj = await resolveToTwTvs(termObj, plotType, llm, dataset_db);
192
- mayLog("Time taken to resolve to TwTvs object from termObj:", formatElapsedTime(Date.now() - time));
193
- if ("type" in twTvsObj && twTvsObj.type === "text") {
194
- return twTvsObj;
195
- }
196
- mayLog("twTvsObj:", twTvsObj);
197
- mayLog("#################################################");
198
- mayLog("####### Fifth/Final phase: From TwTvs Objects to Plot States #######");
199
- mayLog("#################################################");
200
- time = (/* @__PURE__ */ new Date()).valueOf();
201
- ai_output_json = resolveToPlotState(twTvsObj, plotType, subplotType);
202
- mayLog("Time taken to resolve to plot state:", formatElapsedTime(Date.now() - time));
203
- }
204
- return ai_output_json;
205
- }
206
- export {
207
- api,
208
- run_chat_pipeline
209
- };
@@ -1,37 +0,0 @@
1
- import { termdbCohortSummaryPayload } from "#types/checkers";
2
- import { get_ds_tdb } from "#src/termdb.js";
3
- import { get_samples } from "#src/termdb.sql.js";
4
- import { authApi } from "#src/auth.js";
5
- const api = {
6
- endpoint: "termdb/cohort/summary",
7
- methods: {
8
- get: {
9
- ...termdbCohortSummaryPayload,
10
- init
11
- }
12
- }
13
- };
14
- function init({ genomes }) {
15
- return async (req, res) => {
16
- const q = req.query;
17
- try {
18
- const genome = genomes[q.genome];
19
- if (!genome) throw "invalid genome";
20
- const [ds] = get_ds_tdb(genome, q);
21
- authApi.mayAdjustFilter(req.query, ds, []);
22
- let count;
23
- if (q.filter?.lst?.length) {
24
- const samples = await get_samples(q, ds);
25
- count = samples.length;
26
- } else count = ds.cohort.termdb.q?.getCohortSampleCount?.(q.cohort) || 1;
27
- res.send({ count });
28
- } catch (e) {
29
- res.send({ error: e.message || e });
30
- if (e.stack) console.log(e.stack);
31
- else console.log(e);
32
- }
33
- };
34
- }
35
- export {
36
- api
37
- };
@@ -1,41 +0,0 @@
1
- import { termdbCohortsPayload } from "#types/checkers";
2
- import { get_ds_tdb } from "#src/termdb.js";
3
- const api = {
4
- endpoint: "termdb/cohorts",
5
- methods: {
6
- get: {
7
- ...termdbCohortsPayload,
8
- init
9
- }
10
- }
11
- };
12
- function init({ genomes }) {
13
- return async (req, res) => {
14
- const q = req.query;
15
- try {
16
- const genome = genomes[q.genome];
17
- if (!genome) throw "invalid genome";
18
- const [ds] = get_ds_tdb(genome, q);
19
- const result = getCohortsData(ds);
20
- res.send(result);
21
- } catch (e) {
22
- res.send({ error: e.message || e });
23
- if (e.stack) console.log(e.stack);
24
- else console.log(e);
25
- }
26
- };
27
- }
28
- function getCohortsData(ds) {
29
- if (!ds.cohort.db) return { cohorts: [], features: [], cfeatures: [] };
30
- const features = ds.cohort.db.connection.prepare("select * from features").all();
31
- const cohorts = ds.cohort.db.connection.prepare(
32
- `select * from cohorts where cohort in (select distinct(cohort) from cohort_features)
33
- order by sample_count desc`
34
- ).all();
35
- const cfeatures = ds.cohort.db.connection.prepare("select * from cohort_features").all();
36
- return { cohorts, features, cfeatures };
37
- }
38
- export {
39
- api,
40
- getCohortsData
41
- };
@@ -1,80 +0,0 @@
1
- import path from "path";
2
- import fs from "fs/promises";
3
- import { dapVolcanoPayload } from "#types/checkers";
4
- import { get_ds_tdb } from "#src/termdb.js";
5
- import { renderVolcano } from "../src/renderVolcano.ts";
6
- import serverconfig from "../src/serverconfig.js";
7
- import { countDistinctSamples } from "./termdb.proteome.ts";
8
- const api = {
9
- endpoint: "termdb/dapVolcano",
10
- methods: {
11
- get: {
12
- ...dapVolcanoPayload,
13
- init
14
- },
15
- post: {
16
- ...dapVolcanoPayload,
17
- init
18
- }
19
- }
20
- };
21
- function init({ genomes }) {
22
- return async (req, res) => {
23
- try {
24
- const q = req.query;
25
- const genome = genomes[q.genome];
26
- if (!genome) throw "invalid genome";
27
- const [ds] = get_ds_tdb(genome, q);
28
- const proteomeConfig = ds.queries?.proteome;
29
- if (!proteomeConfig) throw "proteome not configured for this dataset";
30
- const organismConfig = proteomeConfig.organisms?.[q.organism];
31
- if (!organismConfig) throw "invalid organism";
32
- const assayConfig = organismConfig.assays?.[q.assay];
33
- if (!assayConfig) throw "invalid assay";
34
- const cohortConfig = assayConfig.cohorts?.[q.cohort];
35
- if (!cohortConfig) throw "invalid cohort";
36
- if (!cohortConfig.DAPfile) throw "DAP file not configured for this cohort";
37
- const organismFilter = [{ columnIdx: organismConfig.columnIdx, columnValue: organismConfig.columnValue }];
38
- const assayFilter = [{ columnIdx: assayConfig.columnIdx, columnValue: assayConfig.columnValue }];
39
- const db = proteomeConfig.db;
40
- const controlCount = countDistinctSamples(db, [...organismFilter, ...assayFilter, ...cohortConfig.controlFilter]);
41
- const caseCount = countDistinctSamples(db, [...organismFilter, ...assayFilter, ...cohortConfig.caseFilter]);
42
- if (q.countsOnly) {
43
- res.send({ sample_size1: controlCount, sample_size2: caseCount });
44
- return;
45
- }
46
- const filePath = path.join(serverconfig.tpmasterdir, cohortConfig.DAPfile);
47
- const content = await fs.readFile(filePath, "utf8");
48
- const lines = content.trim().split("\n");
49
- const rustRows = [];
50
- for (let i = 1; i < lines.length; i++) {
51
- const parts = lines[i].split(" ");
52
- if (parts.length < 4) continue;
53
- const fc = Number(parts[2]);
54
- if (!Number.isFinite(fc)) continue;
55
- const pValue = Number(parts[3]);
56
- if (!Number.isFinite(pValue)) continue;
57
- rustRows.push({
58
- gene_name: parts[0],
59
- gene: parts[1],
60
- fold_change: fc,
61
- original_p_value: pValue,
62
- adjusted_p_value: pValue
63
- });
64
- }
65
- const rendered = await renderVolcano(rustRows, q.volcanoRender);
66
- for (const d of rendered.dots) delete d.adjusted_p_value;
67
- res.send({
68
- data: rendered,
69
- sample_size1: controlCount,
70
- sample_size2: caseCount
71
- });
72
- } catch (e) {
73
- res.send({ status: "error", error: e.message || e });
74
- if (e instanceof Error && e.stack) console.log(e);
75
- }
76
- };
77
- }
78
- export {
79
- api
80
- };
@@ -1,93 +0,0 @@
1
- import { TermdbDmrPayload } from "#types/checkers";
2
- import { run_rust } from "@sjcrh/proteinpaint-rust";
3
- import { run_R } from "@sjcrh/proteinpaint-r";
4
- import { invalidcoord } from "#shared/common.js";
5
- import { mayLog } from "#src/helpers.ts";
6
- import serverconfig from "#src/serverconfig.js";
7
- import { formatElapsedTime } from "#shared";
8
- const api = {
9
- endpoint: "termdb/dmr",
10
- methods: {
11
- get: {
12
- ...TermdbDmrPayload,
13
- init
14
- },
15
- post: {
16
- ...TermdbDmrPayload,
17
- init
18
- }
19
- }
20
- };
21
- function init({ genomes }) {
22
- return async (req, res) => {
23
- try {
24
- const q = req.query;
25
- const genome = genomes[q.genome];
26
- if (!genome) throw "unknown genome";
27
- const ds = genome.datasets?.[q.dslabel];
28
- if (!ds) throw "unknown ds";
29
- if (!ds.queries?.dnaMethylation) throw new Error("This dataset does not support DNA methylation analysis.");
30
- if (!Array.isArray(q.group1) || q.group1.length == 0)
31
- throw new Error("Group 1 has no samples. Please select at least one sample.");
32
- if (!Array.isArray(q.group2) || q.group2.length == 0)
33
- throw new Error("Group 2 has no samples. Please select at least one sample.");
34
- if (invalidcoord(genome, q.chr, q.start, q.stop))
35
- throw new Error(`Invalid genomic coordinates: ${q.chr}:${q.start}-${q.stop}`);
36
- const SERVER_MAX_REGION_BP = 1e7;
37
- const span = q.stop - q.start;
38
- if (span > SERVER_MAX_REGION_BP)
39
- throw new Error(
40
- `Region too large (${(span / 1e6).toFixed(1)} Mb). Server maximum is ${SERVER_MAX_REGION_BP / 1e6} Mb.`
41
- );
42
- const group1 = q.group1.map((s) => s.sample).filter(Boolean);
43
- const group2 = q.group2.map((s) => s.sample).filter(Boolean);
44
- if (group1.length < 3)
45
- throw new Error(`Group 1 needs at least 3 samples with methylation data, got ${group1.length}.`);
46
- if (group2.length < 3)
47
- throw new Error(`Group 2 needs at least 3 samples with methylation data, got ${group2.length}.`);
48
- const useR = q.backend === "r";
49
- const dmrInput = {
50
- probe_h5_file: ds.queries.dnaMethylation.file,
51
- cachedir: serverconfig.cachedir,
52
- genome: q.genome,
53
- chr: q.chr,
54
- start: q.start,
55
- stop: q.stop,
56
- case: group2.join(","),
57
- control: group1.join(","),
58
- fdr_cutoff: q.fdr_cutoff,
59
- lambda: q.lambda,
60
- C: q.C,
61
- blockWidth: q.blockWidth,
62
- devicePixelRatio: q.devicePixelRatio,
63
- maxLoessRegion: q.maxLoessRegion,
64
- colors: q.colors
65
- };
66
- const time1 = Date.now();
67
- const result = useR ? JSON.parse(await run_R("dmrcate_full.R", JSON.stringify(dmrInput))) : JSON.parse(await run_rust("dmrcate", JSON.stringify(dmrInput)));
68
- mayLog(`DMR analysis (${useR ? "R" : "Rust"}) time:`, formatElapsedTime(Date.now() - time1));
69
- if (result.error) throw new Error(result.error);
70
- if (result.diagnostic?.probes) {
71
- const p = result.diagnostic.probes;
72
- mayLog(
73
- `${useR ? "R" : "Rust"} probes logFC:`,
74
- p.logFC,
75
- "fdr:",
76
- p.fdr?.map((f) => f.toExponential(4))
77
- );
78
- }
79
- res.send({
80
- status: "ok",
81
- dmrs: result.dmrs,
82
- diagnostic: result.diagnostic
83
- });
84
- } catch (e) {
85
- const msg = e instanceof Error ? e.message : String(e);
86
- res.send({ error: msg });
87
- if (e instanceof Error && e.stack) console.log(e);
88
- }
89
- };
90
- }
91
- export {
92
- api
93
- };
@@ -1,89 +0,0 @@
1
- import { FilterTermValuesPayload } from "#types/checkers";
2
- import { getData } from "../src/termdb.matrix.js";
3
- import { authApi } from "#src/auth.js";
4
- import { filterJoin } from "#shared/filter.js";
5
- import { get_samples } from "../src/termdb.sql.js";
6
- const api = {
7
- endpoint: "termdb/filterTermValues",
8
- methods: {
9
- get: {
10
- ...FilterTermValuesPayload,
11
- init
12
- },
13
- post: {
14
- ...FilterTermValuesPayload,
15
- init
16
- }
17
- }
18
- };
19
- function init({ genomes }) {
20
- return async (req, res) => {
21
- try {
22
- const g = genomes[req.query.genome];
23
- if (!g) throw "invalid genome name";
24
- const ds = g.datasets?.[req.query.dslabel];
25
- res.send(await getFilters(req.query, ds));
26
- } catch (e) {
27
- if (e.stack) console.log(e.stack);
28
- res.send({ status: "error", error: e.message || e });
29
- }
30
- };
31
- }
32
- async function getFilters(query, ds) {
33
- const samplesPerFilter = await getSamplesPerFilter(query, ds);
34
- const filtersData = await getData(
35
- {
36
- terms: query.terms,
37
- __protected__: query.__protected__
38
- },
39
- ds
40
- );
41
- const tw2List = {};
42
- for (const tw of query.terms) {
43
- const values = getList(samplesPerFilter, filtersData, tw, query.showAll);
44
- tw2List[tw.term.id] = values;
45
- }
46
- return { ...tw2List };
47
- }
48
- async function getSamplesPerFilter(q, ds) {
49
- q.ds = ds;
50
- const samples = {};
51
- const userFilter = q.filter ? structuredClone(q.filter) : null;
52
- if (!q.filterByUserSites) {
53
- q.__protected__.ignoredTermIds.push(q.facilityTW.term.id);
54
- authApi.mayAdjustFilter(q, ds, q.terms);
55
- }
56
- for (const id in q.filters) {
57
- const termfilter = id == q.facilityTW.term.id ? userFilter : q.filter;
58
- let filter = q.filters[id];
59
- if (q.filter) filter = filterJoin([termfilter, q.filters[id]]);
60
- const result = (await get_samples({ filter, __protected__: q.__protected__ }, q.ds)).map((i) => i.id);
61
- samples[id] = Array.from(new Set(result));
62
- }
63
- return samples;
64
- }
65
- function getList(samplesPerFilter, filtersData, tw, showAll) {
66
- const values = Object.values(tw.term.values);
67
- values.sort((v1, v2) => v1.label.localeCompare(v2.label));
68
- const twSamples = samplesPerFilter[tw.term.id];
69
- const data = [];
70
- for (const sample of twSamples) {
71
- data.push(filtersData.samples[sample]);
72
- }
73
- const annotations = data.filter((s) => s != void 0).map((sample) => sample[tw.$id]?.value);
74
- const sampleValues = Array.from(new Set(annotations));
75
- const filteredValues = [];
76
- for (const value of values) {
77
- let label = value.label.replace(/["']/g, "");
78
- if (label.length > 50) label = label.slice(0, 47) + "...";
79
- const disabled = !sampleValues.includes(value.key || value.label);
80
- if (!showAll && disabled) continue;
81
- filteredValues.push({ value: value.key || value.label, label, disabled });
82
- }
83
- filteredValues.unshift({ label: "", value: "" });
84
- filteredValues.sort((a, b) => a.label.localeCompare(b.label));
85
- return filteredValues;
86
- }
87
- export {
88
- api
89
- };
@@ -1,35 +0,0 @@
1
- import { TermdbIsoformAvailabilityPayload } from "#types/checkers";
2
- const api = {
3
- endpoint: "termdb/isoformAvailability",
4
- methods: {
5
- get: {
6
- ...TermdbIsoformAvailabilityPayload,
7
- init
8
- },
9
- post: {
10
- ...TermdbIsoformAvailabilityPayload,
11
- init
12
- }
13
- }
14
- };
15
- function init({ genomes }) {
16
- return (req, res) => {
17
- try {
18
- const q = req.query;
19
- const genome = genomes[q.genome];
20
- if (!genome) throw "invalid genome";
21
- const ds = genome.datasets?.[q.dslabel];
22
- if (!ds) throw "invalid dslabel";
23
- const isoQ = ds.queries?.isoformExpression;
24
- if (!isoQ) throw "isoformExpression not configured for this dataset";
25
- const itemSet = new Set(isoQ.availableItems || []);
26
- const available = (q.isoforms || []).filter((id) => itemSet.has(id));
27
- res.send({ available });
28
- } catch (e) {
29
- res.send({ error: e.message || e });
30
- }
31
- };
32
- }
33
- export {
34
- api
35
- };
@@ -1,46 +0,0 @@
1
- import { numericCategoriesPayload } from "#types/checkers";
2
- import * as termdbsql from "#src/termdb.sql.js";
3
- const api = {
4
- endpoint: "termdb/numericcategories",
5
- methods: {
6
- get: {
7
- ...numericCategoriesPayload,
8
- init
9
- },
10
- post: {
11
- ...numericCategoriesPayload,
12
- init
13
- }
14
- }
15
- };
16
- function init({ genomes }) {
17
- return async (req, res) => {
18
- const q = req.query;
19
- try {
20
- const g = genomes[req.query.genome];
21
- if (!g) throw "invalid genome name";
22
- const ds = g.datasets[req.query.dslabel];
23
- if (!ds) throw "invalid dataset name";
24
- const tdb = ds.cohort.termdb;
25
- if (!tdb) throw "invalid termdb object";
26
- const result = await trigger_getnumericcategories(q, tdb, ds);
27
- res.send(result);
28
- } catch (e) {
29
- res.send({ error: e instanceof Error ? e.message : e });
30
- if (e instanceof Error && e.stack) console.log(e);
31
- }
32
- };
33
- }
34
- async function trigger_getnumericcategories(q, tdb, ds) {
35
- if (!q.tid) throw ".tid missing";
36
- const arg = {
37
- ds,
38
- term_id: q.tid,
39
- filter: q.filter
40
- };
41
- const lst = await termdbsql.get_summary_numericcategories(arg);
42
- return { lst };
43
- }
44
- export {
45
- api
46
- };