@sjcrh/proteinpaint-server 2.155.1-0 → 2.157.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjcrh/proteinpaint-server",
3
- "version": "2.155.1-0",
3
+ "version": "2.157.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",
@@ -61,11 +61,11 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@sjcrh/augen": "2.143.0",
64
- "@sjcrh/proteinpaint-python": "2.153.1-3",
64
+ "@sjcrh/proteinpaint-python": "2.157.0",
65
65
  "@sjcrh/proteinpaint-r": "2.152.1-0",
66
- "@sjcrh/proteinpaint-rust": "2.152.1-0",
67
- "@sjcrh/proteinpaint-shared": "2.153.1-2",
68
- "@sjcrh/proteinpaint-types": "2.153.1-2",
66
+ "@sjcrh/proteinpaint-rust": "2.157.0",
67
+ "@sjcrh/proteinpaint-shared": "2.157.0",
68
+ "@sjcrh/proteinpaint-types": "2.157.0",
69
69
  "@types/express": "^5.0.0",
70
70
  "@types/express-session": "^1.18.1",
71
71
  "better-sqlite3": "^12.4.1",
package/routes/grin2.js CHANGED
@@ -2,6 +2,7 @@ import { GRIN2Payload } from "#types/checkers";
2
2
  import serverconfig from "#src/serverconfig.js";
3
3
  import path from "path";
4
4
  import { run_python } from "@sjcrh/proteinpaint-python";
5
+ import { run_rust } from "@sjcrh/proteinpaint-rust";
5
6
  import { mayLog } from "#src/helpers.ts";
6
7
  import { get_samples } from "#src/termdb.sql.js";
7
8
  import { read_file, file_is_readable } from "#src/utils.js";
@@ -88,10 +89,6 @@ async function runGrin2(g, ds, request) {
88
89
  genedb: path.join(serverconfig.tpmasterdir, g.genedb.dbfile),
89
90
  chromosomelist: {},
90
91
  lesion: JSON.stringify(lesions),
91
- devicePixelRatio: request.devicePixelRatio,
92
- pngDotRadius: request.pngDotRadius,
93
- width: request.width,
94
- height: request.height,
95
92
  cacheFileName: generateCacheFileName(),
96
93
  availableDataTypes: getAvailableDataTypes(request),
97
94
  maxGenesToShow: request.maxGenesToShow
@@ -114,14 +111,29 @@ async function runGrin2(g, ds, request) {
114
111
  const grin2AnalysisTimeToPrint = Math.round(grin2AnalysisTime / 1e3);
115
112
  mayLog(`[GRIN2] Python processing took ${grin2AnalysisTimeToPrint} seconds`);
116
113
  const resultData = JSON.parse(pyResult);
117
- if (!resultData?.png?.[0]) {
118
- throw new Error("Invalid Python output: missing PNG data");
114
+ const rustInput = {
115
+ file: resultData.cacheFileName,
116
+ type: "grin2",
117
+ chrSizes: pyInput.chromosomelist,
118
+ plot_width: request.width,
119
+ plot_height: request.height,
120
+ device_pixel_ratio: request.devicePixelRatio,
121
+ png_dot_radius: request.pngDotRadius
122
+ };
123
+ const manhattanPlotStart = Date.now();
124
+ const rsResult = await run_rust("manhattan_plot", JSON.stringify(rustInput));
125
+ const manhattanPlotTime = Date.now() - manhattanPlotStart;
126
+ const manhattanPlotTimeToPrint = Math.round(manhattanPlotTime / 1e3);
127
+ mayLog(`[GRIN2] Manhattan plot generation took ${manhattanPlotTimeToPrint} seconds`);
128
+ const manhattanPlotData = JSON.parse(rsResult);
129
+ if (!manhattanPlotData?.png) {
130
+ throw new Error("Invalid Rust output: missing PNG data");
119
131
  }
120
132
  const totalTime = Math.round((Date.now() - startTime) / 1e3);
121
133
  const response = {
122
134
  status: "success",
123
- pngImg: resultData.png[0],
124
- plotData: resultData.plotData,
135
+ pngImg: manhattanPlotData.png,
136
+ plotData: manhattanPlotData.plot_data,
125
137
  topGeneTable: resultData.topGeneTable,
126
138
  totalGenes: resultData.totalGenes,
127
139
  showingTop: resultData.showingTop,
@@ -11,7 +11,7 @@ import imagesize from "image-size";
11
11
  import { get_header_txt } from "#src/utils.js";
12
12
  import { formatElapsedTime } from "@sjcrh/proteinpaint-shared/time.js";
13
13
  const api = {
14
- endpoint: "DEanalysis",
14
+ endpoint: "termdb/DE",
15
15
  methods: {
16
16
  get: {
17
17
  ...diffExpPayload,
@@ -28,7 +28,7 @@ function init({ genomes }) {
28
28
  try {
29
29
  const q = req.query;
30
30
  const genome = genomes[q.genome];
31
- if (!genome) throw "invalid genome";
31
+ if (!genome) throw new Error("invalid genome");
32
32
  const [ds] = get_ds_tdb(genome, q);
33
33
  let term_results = [];
34
34
  if (q.tw) {
@@ -41,7 +41,7 @@ function init({ genomes }) {
41
41
  },
42
42
  ds
43
43
  );
44
- if (term_results.error) throw term_results.error;
44
+ if (term_results.error) throw new Error(term_results.error);
45
45
  }
46
46
  let term_results2 = [];
47
47
  if (q.tw2) {
@@ -54,10 +54,10 @@ function init({ genomes }) {
54
54
  },
55
55
  ds
56
56
  );
57
- if (term_results2.error) throw term_results2.error;
57
+ if (term_results2.error) throw new Error(term_results2.error);
58
58
  }
59
59
  const results = await run_DE(req.query, ds, term_results, term_results2);
60
- if (!results || !results.data) throw "No data [termdb.DE.ts init()]";
60
+ if (!results || !results.data) throw new Error("No data available");
61
61
  res.send(results);
62
62
  } catch (e) {
63
63
  res.send({ status: "error", error: e.message || e });
@@ -66,13 +66,13 @@ function init({ genomes }) {
66
66
  };
67
67
  }
68
68
  async function run_DE(param, ds, term_results, term_results2) {
69
- if (param.samplelst?.groups?.length != 2) throw ".samplelst.groups.length!=2";
70
- if (param.samplelst.groups[0].values?.length < 1) throw "samplelst.groups[0].values.length<1";
71
- if (param.samplelst.groups[1].values?.length < 1) throw "samplelst.groups[1].values.length<1";
69
+ if (param.samplelst?.groups?.length != 2) throw new Error(".samplelst.groups.length!=2");
70
+ if (param.samplelst.groups[0].values?.length < 1) throw new Error("samplelst.groups[0].values.length<1");
71
+ if (param.samplelst.groups[1].values?.length < 1) throw new Error("samplelst.groups[1].values.length<1");
72
72
  const q = ds.queries.rnaseqGeneCount;
73
73
  if (!q) return;
74
- if (!q.file) throw "unknown data type for rnaseqGeneCount";
75
- if (!q.storage_type) throw "storage_type is not defined";
74
+ if (!q.file) throw new Error("unknown data type for rnaseqGeneCount");
75
+ if (!q.storage_type) throw new Error("storage_type is not defined");
76
76
  param.storage_type = q.storage_type;
77
77
  const group1names = [];
78
78
  const conf1_group1 = [];
@@ -178,7 +178,7 @@ async function run_DE(param, ds, term_results, term_results2) {
178
178
  }
179
179
  };
180
180
  }
181
- if (alerts.length) throw alerts.join(" | ");
181
+ if (alerts.length) throw new Error(alerts.join(" | "));
182
182
  const cases_string = group2names.map((i) => i).join(",");
183
183
  const controls_string = group1names.map((i) => i).join(",");
184
184
  const expression_input = {
@@ -199,14 +199,14 @@ async function run_DE(param, ds, term_results, term_results2) {
199
199
  expression_input.conf1 = [...conf1_group2, ...conf1_group1];
200
200
  expression_input.conf1_mode = param.tw.q.mode;
201
201
  if (new Set(expression_input.conf1).size === 1) {
202
- throw "Confounding variable 1 has only one value";
202
+ throw new Error("Confounding variable 1 has only one value");
203
203
  }
204
204
  }
205
205
  if (param.tw2) {
206
206
  expression_input.conf2 = [...conf2_group2, ...conf2_group1];
207
207
  expression_input.conf2_mode = param.tw2.q.mode;
208
208
  if (new Set(expression_input.conf2).size === 1) {
209
- throw "Confounding variable 2 has only one value";
209
+ throw new Error("Confounding variable 2 has only one value");
210
210
  }
211
211
  }
212
212
  const sample_size_limit = 8;
@@ -261,13 +261,13 @@ async function readFileAndDelete(file, key, response) {
261
261
  };
262
262
  response[key] = obj;
263
263
  fs.unlink(file, (err) => {
264
- if (err) throw err;
264
+ if (err) throw new Error(err.message || String(err));
265
265
  });
266
266
  }
267
267
  async function validate_query_rnaseqGeneCount(ds) {
268
268
  const q = ds.queries.rnaseqGeneCount;
269
269
  if (!q) return;
270
- if (!q.file) throw "unknown data type for rnaseqGeneCount";
270
+ if (!q.file) throw new Error("unknown data type for rnaseqGeneCount");
271
271
  q.file = path.join(serverconfig.tpmasterdir, q.file);
272
272
  {
273
273
  let samples = [];
@@ -283,10 +283,10 @@ async function validate_query_rnaseqGeneCount(ds) {
283
283
  const time2 = (/* @__PURE__ */ new Date()).valueOf();
284
284
  mayLog("Time taken to query gene expression:", time2 - time1, "ms");
285
285
  const vr = JSON.parse(result);
286
- if (vr.status !== "success") throw vr.message;
287
- if (!Array.isArray(vr.samples)) throw "HDF5 file has no samples, please check file.";
286
+ if (vr.status !== "success") throw new Error(vr.message);
287
+ if (!Array.isArray(vr.samples)) throw new Error("HDF5 file has no samples, please check file.");
288
288
  samples = vr.samples;
289
- } else throw "unknown storage type:" + ds.queries.rnaseqGeneCount.storage_type;
289
+ } else throw new Error("unknown storage type:" + ds.queries.rnaseqGeneCount.storage_type);
290
290
  q.allSampleSet = new Set(samples);
291
291
  const unknownSamples = [];
292
292
  for (const n of q.allSampleSet) {
@@ -19,12 +19,13 @@ function init({ genomes }) {
19
19
  let result;
20
20
  try {
21
21
  const g = genomes[q.genome];
22
- if (!g) throw "invalid genome name";
22
+ if (!g) throw new Error("invalid genome name");
23
23
  const ds = g.datasets[q.dslabel];
24
- if (!ds) throw "invalid dataset name";
25
- if (!ds.queries?.singleCell?.DEgenes) throw "not supported on this dataset";
24
+ if (!ds) throw new Error("invalid dataset name");
25
+ if (!ds.queries?.singleCell?.DEgenes || !ds.queries.singleCell.DEgenes.get)
26
+ throw new Error("DE genes not supported on this dataset.");
26
27
  result = await ds.queries.singleCell.DEgenes.get(q);
27
- if (!result || !result.genes || !result?.genes?.length) {
28
+ if (!result || !result.data || !result?.data?.length) {
28
29
  result = {
29
30
  status: 404,
30
31
  error: !result ? "No data found." : "No differentially expressed genes found."
@@ -44,7 +45,7 @@ async function validate_query_singleCell_DEgenes(ds) {
44
45
  if (ds.queries.singleCell.DEgenes.src == "gdcapi") {
45
46
  gdc_validate_query_singleCell_DEgenes(ds);
46
47
  } else {
47
- throw "unknown singleCell.DEgenes.src";
48
+ throw new Error("unknown singleCell.DEgenes.src");
48
49
  }
49
50
  }
50
51
  export {