@sjcrh/proteinpaint-server 2.112.0 → 2.113.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.112.0",
3
+ "version": "2.113.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",
@@ -18,6 +18,9 @@
18
18
  "prestart": "tsx emitImports.js dev > server.js",
19
19
  "start": "tsx watch . /start.js",
20
20
  "test:unit": "tsx emitImports.js unit > serverTests.js && c8 tsx serverTests.js && rm -rf ./cache",
21
+ "precombined:coverage": "tsx emitImports.js unit > serverTests.js",
22
+ "combined:coverage": "closeCoverageKey=test c8 --all --src=proteinpaint/server --experimental-monocart -r=v8 -r=html -r=json -r=markdown-summary -r=markdown-details -o=./.coverage tsx ./coverage.js & ",
23
+ "postcombined:coverage": "rm -rf ./cache",
21
24
  "getconf": "../build/getConfigProp.js",
22
25
  "doc": "../augen/build.sh routes shared/types/routes shared/checkers ../public/docs/server",
23
26
  "mjs": "esbuild \"$DIR/*.ts\" --platform=node --outdir=\"$DIR\" --format=esm",
@@ -49,6 +52,8 @@
49
52
  "c8": "^10.1.3",
50
53
  "esbuild": "^0.19.12",
51
54
  "glob": "^10.4.5",
55
+ "monocart-coverage-reports": "^2.12.1",
56
+ "node-notifier": "^9.0.1",
52
57
  "node-watch": "^0.7.1",
53
58
  "nodemon": "^2.0.19",
54
59
  "prettier": "^2.8.8",
@@ -59,10 +64,10 @@
59
64
  "typescript": "^5.6.3"
60
65
  },
61
66
  "dependencies": {
62
- "@sjcrh/augen": "2.109.1-0",
67
+ "@sjcrh/augen": "2.113.0",
63
68
  "@sjcrh/proteinpaint-rust": "2.112.0",
64
- "@sjcrh/proteinpaint-shared": "2.112.0",
65
- "@sjcrh/proteinpaint-types": "2.112.0",
69
+ "@sjcrh/proteinpaint-shared": "2.113.0",
70
+ "@sjcrh/proteinpaint-types": "2.113.0",
66
71
  "@types/express": "^5.0.0",
67
72
  "@types/express-session": "^1.18.1",
68
73
  "better-sqlite3": "^9.4.1",
@@ -196,7 +196,10 @@ async function run_DE(param, ds, term_results, term_results2) {
196
196
  cachedir: serverconfig.cachedir,
197
197
  min_count: param.min_count,
198
198
  min_total_count: param.min_total_count,
199
- storage_type: param.storage_type
199
+ storage_type: param.storage_type,
200
+ DE_method: param.method,
201
+ mds_cutoff: 1e4
202
+ // If the dimensions of the read counts matrix is below this threshold, only then the mds image will be generated as its very compute intensive. Number of genes * Number of samples < mds_cutoff for mds generation
200
203
  };
201
204
  if (param.tw) {
202
205
  expression_input.conf1 = [...conf1_group2, ...conf1_group1];
@@ -213,7 +216,7 @@ async function run_DE(param, ds, term_results, term_results2) {
213
216
  }
214
217
  }
215
218
  const sample_size_limit = 8;
216
- if (group1names.length <= sample_size_limit && group2names.length <= sample_size_limit || param.method == "edgeR") {
219
+ if (group1names.length <= sample_size_limit && group2names.length <= sample_size_limit || param.method == "edgeR" || param.method == "limma") {
217
220
  const time12 = (/* @__PURE__ */ new Date()).valueOf();
218
221
  const result2 = JSON.parse(
219
222
  await run_R(path.join(serverconfig.binpath, "utils", "edge.R"), JSON.stringify(expression_input))
@@ -222,21 +225,21 @@ async function run_DE(param, ds, term_results, term_results2) {
222
225
  param.method = "edgeR";
223
226
  const ql_imagePath = path.join(serverconfig.cachedir, result2.edgeR_ql_image_name[0]);
224
227
  mayLog("ql_imagePath:", ql_imagePath);
225
- const mds_imagePath = path.join(serverconfig.cachedir, result2.edgeR_mds_image_name[0]);
226
- mayLog("mds_imagePath:", mds_imagePath);
227
- await readFileAndDelete(mds_imagePath, "mds_image", result2);
228
228
  await readFileAndDelete(ql_imagePath, "ql_image", result2);
229
+ if (result2.edgeR_mds_image_name) {
230
+ const mds_imagePath = path.join(serverconfig.cachedir, result2.edgeR_mds_image_name[0]);
231
+ mayLog("mds_imagePath:", mds_imagePath);
232
+ await readFileAndDelete(mds_imagePath, "mds_image", result2);
233
+ }
234
+ const images = [result2.ql_image];
235
+ if (result2.mds_image)
236
+ images.push(result2.mds_image);
229
237
  return {
230
238
  data: result2.gene_data,
231
239
  sample_size1,
232
240
  sample_size2,
233
241
  method: param.method,
234
- images: [
235
- result2.mds_image,
236
- // MDS image
237
- result2.ql_image
238
- // QL fit image
239
- ]
242
+ images
240
243
  };
241
244
  }
242
245
  const time1 = (/* @__PURE__ */ new Date()).valueOf();
@@ -259,7 +262,7 @@ async function readFileAndDelete(file, key, response) {
259
262
  throw err;
260
263
  });
261
264
  }
262
- async function validate_query_rnaseqGeneCount(ds, genome) {
265
+ async function validate_query_rnaseqGeneCount(ds) {
263
266
  const q = ds.queries.rnaseqGeneCount;
264
267
  if (!q)
265
268
  return;
@@ -278,6 +281,7 @@ async function validate_query_rnaseqGeneCount(ds, genome) {
278
281
  const time1 = (/* @__PURE__ */ new Date()).valueOf();
279
282
  const result = await run_rust("DEanalysis", JSON.stringify(get_samples_from_hdf5));
280
283
  const time2 = (/* @__PURE__ */ new Date()).valueOf();
284
+ mayLog("Time taken to query gene expression:", time2 - time1, "ms");
281
285
  samples = result.split(",");
282
286
  } else
283
287
  throw "unknown storage type:" + ds.queries.rnaseqGeneCount.storage_type;
@@ -67,22 +67,32 @@ async function getResult(q, ds, genome) {
67
67
  _q = JSON.parse(JSON.stringify(q));
68
68
  _q.forClusteringAnalysis = true;
69
69
  }
70
- let term2sample2value, byTermId, bySampleId;
70
+ let term2sample2value, byTermId, bySampleId, skippedSexChrGenes;
71
71
  if (q.dataType == NUMERIC_DICTIONARY_TERM) {
72
72
  ;
73
73
  ({ term2sample2value, byTermId, bySampleId } = await getNumericDictTermAnnotation(q, ds, genome));
74
74
  } else {
75
75
  ;
76
- ({ term2sample2value, byTermId, bySampleId } = await ds.queries[q.dataType].get(_q));
76
+ ({ term2sample2value, byTermId, bySampleId, skippedSexChrGenes } = await ds.queries[q.dataType].get(_q));
77
77
  }
78
- const removedHierClusterTerms = [];
78
+ const noValueTerms = [];
79
79
  for (const [term, obj] of term2sample2value) {
80
80
  if (Object.keys(obj).length === 0) {
81
- removedHierClusterTerms.push(term);
81
+ noValueTerms.push(term);
82
82
  term2sample2value.delete(term);
83
83
  delete byTermId[term];
84
84
  }
85
85
  }
86
+ const removedHierClusterTerms = [];
87
+ if (noValueTerms.length) {
88
+ removedHierClusterTerms.push({
89
+ text: `Skipped ${q.dataType == TermTypes.GENE_EXPRESSION ? "genes" : "items"} with no data`,
90
+ lst: noValueTerms
91
+ });
92
+ }
93
+ if (skippedSexChrGenes?.length) {
94
+ removedHierClusterTerms.push({ text: "Skipped sex chromosome genes", lst: skippedSexChrGenes });
95
+ }
86
96
  if (term2sample2value.size == 0)
87
97
  throw "no data";
88
98
  if (term2sample2value.size == 1) {
@@ -164,9 +164,6 @@ function addNonDictionaryQueries(c, ds, genome) {
164
164
  }
165
165
  if (q.ld) {
166
166
  q2.ld = JSON.parse(JSON.stringify(q.ld));
167
- for (const i of q2.ld.tracks) {
168
- delete i.file;
169
- }
170
167
  }
171
168
  if (q.cnv) {
172
169
  q2.cnv = {};