@sjcrh/proteinpaint-server 2.178.0 → 2.178.1-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.178.0",
3
+ "version": "2.178.1-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",
@@ -65,8 +65,8 @@
65
65
  "@sjcrh/proteinpaint-python": "2.178.0",
66
66
  "@sjcrh/proteinpaint-r": "2.178.0",
67
67
  "@sjcrh/proteinpaint-rust": "2.178.0",
68
- "@sjcrh/proteinpaint-shared": "2.178.0",
69
- "@sjcrh/proteinpaint-types": "2.178.0",
68
+ "@sjcrh/proteinpaint-shared": "2.178.1-0",
69
+ "@sjcrh/proteinpaint-types": "2.178.1-0",
70
70
  "@types/express": "^5.0.0",
71
71
  "@types/express-session": "^1.18.1",
72
72
  "better-sqlite3": "^12.4.1",
@@ -22,14 +22,14 @@ const api = {
22
22
  function init({ genomes }) {
23
23
  return async (req, res) => {
24
24
  const q = req.query;
25
- const genome = genomes[q.genome];
26
- if (!genome) throw new Error("invalid genome name");
27
- const ds = genome.datasets?.[q.dslabel];
28
- if (!ds) throw new Error("invalid ds");
29
- const terms = [q.tw];
30
- if (q.overlayTw) terms.push(q.overlayTw);
31
- if (q.divideTw) terms.push(q.divideTw);
32
25
  try {
26
+ const genome = genomes[q.genome];
27
+ if (!genome) throw new Error("invalid genome name");
28
+ const ds = genome.datasets?.[q.dslabel];
29
+ if (!ds) throw new Error("invalid dslabel");
30
+ const terms = [q.tw];
31
+ if (q.overlayTw) terms.push(q.overlayTw);
32
+ if (q.divideTw) terms.push(q.divideTw);
33
33
  const data = await getData(
34
34
  { filter: q.filter, filter0: q.filter0, terms, __protected__: q.__protected__, __abortSignal: q.__abortSignal },
35
35
  ds
@@ -7,6 +7,7 @@ import { extract_DE_search_terms_from_query } from "./chat/DEagent.ts";
7
7
  import { extract_summary_terms } from "./chat/summaryagent.ts";
8
8
  import { extract_matrix_search_terms_from_query } from "./chat/matrixagent.ts";
9
9
  import { extract_samplescatter_terms_from_query } from "./chat/samplescatteragent.ts";
10
+ import { extract_hiercluster_terms_from_query } from "./chat/hierclusteragent.ts";
10
11
  import { parse_dataset_db, parse_geneset_db, getGenesetNames } from "./chat/utils.ts";
11
12
  import serverconfig from "../src/serverconfig.js";
12
13
  import { mayLog } from "#src/helpers.ts";
@@ -50,7 +51,6 @@ function init({ genomes }) {
50
51
  const ai_output_json = await run_chat_pipeline(
51
52
  q.prompt,
52
53
  llm,
53
- serverconfig.aiRoute,
54
54
  dataset_json,
55
55
  testing,
56
56
  dataset_db,
@@ -65,7 +65,7 @@ function init({ genomes }) {
65
65
  }
66
66
  };
67
67
  }
68
- async function run_chat_pipeline(user_prompt, llm, aiRoute, dataset_json, testing, dataset_db, genedb, ds, genesetNames = []) {
68
+ async function run_chat_pipeline(user_prompt, llm, dataset_json, testing, dataset_db, genedb, ds, genesetNames = []) {
69
69
  const time1 = (/* @__PURE__ */ new Date()).valueOf();
70
70
  const class_response = await classifyQuery(user_prompt, llm);
71
71
  let ai_output_json;
@@ -84,9 +84,8 @@ async function run_chat_pipeline(user_prompt, llm, aiRoute, dataset_json, testin
84
84
  }
85
85
  } else if (class_response.type == "plot") {
86
86
  const classResult = await classifyPlotType(user_prompt, llm);
87
- mayLog("classResult:", classResult);
88
87
  const dataset_db_output = await parse_dataset_db(dataset_db);
89
- const genes_list = dataset_json.hasGeneExpression ? await parse_geneset_db(genedb) : [];
88
+ const genes_list = await parse_geneset_db(genedb);
90
89
  if (classResult == "summary") {
91
90
  const time12 = (/* @__PURE__ */ new Date()).valueOf();
92
91
  ai_output_json = await extract_summary_terms(
@@ -139,6 +138,19 @@ async function run_chat_pipeline(user_prompt, llm, aiRoute, dataset_json, testin
139
138
  genesetNames
140
139
  );
141
140
  mayLog("Time taken for sampleScatter agent:", formatElapsedTime(Date.now() - time12));
141
+ } else if (classResult == "hiercluster") {
142
+ const time12 = (/* @__PURE__ */ new Date()).valueOf();
143
+ ai_output_json = await extract_hiercluster_terms_from_query(
144
+ user_prompt,
145
+ llm,
146
+ dataset_db_output,
147
+ dataset_json,
148
+ genes_list,
149
+ ds,
150
+ testing,
151
+ genesetNames
152
+ );
153
+ mayLog("Time taken for hierCluster agent:", formatElapsedTime(Date.now() - time12));
142
154
  } else {
143
155
  ai_output_json = { type: "text", text: "Unknown classification value" };
144
156
  }
@@ -23,15 +23,15 @@ const api = {
23
23
  const refColor = "#F5F5DC";
24
24
  function init({ genomes }) {
25
25
  return async function(req, res) {
26
- const q = req.query;
27
- if (!q.genome || !q.dslabel) {
28
- throw new Error("Genome and dataset label are required for termdb/sampleScatter request.");
29
- }
30
- const g = genomes[q.genome];
31
- const ds = g.datasets[q.dslabel];
32
- if (q.singleCellPlot)
33
- return getSingleCellScatter(req, res, ds);
34
26
  try {
27
+ const q = req.query;
28
+ if (!q.genome || !q.dslabel) {
29
+ throw new Error("Genome and dataset label are required for termdb/sampleScatter request.");
30
+ }
31
+ const g = genomes[q.genome];
32
+ const ds = g.datasets[q.dslabel];
33
+ if (q.singleCellPlot)
34
+ return getSingleCellScatter(req, res, ds);
35
35
  let refSamples = [], cohortSamples;
36
36
  const terms = [];
37
37
  if (q.colorTW) terms.push(q.colorTW);
@@ -190,9 +190,10 @@ async function createCanvasImg(q, result, ds) {
190
190
  const chart = result.charts[k];
191
191
  const plot2Values = {};
192
192
  for (const plot of chart.plots) plot2Values[plot.label] = plot.values;
193
- const densities = await getDensities(plot2Values);
194
- let axisScale;
195
193
  const useLog = q.unit == "log";
194
+ const logBase = ds.cohort.termdb.logscaleBase2 ? 2 : 10;
195
+ const densities = await getDensities(plot2Values, useLog, logBase);
196
+ let axisScale;
196
197
  if (useLog) {
197
198
  axisScale = scaleLog().base(ds.cohort.termdb.logscaleBase2 ? 2 : 10).domain([result.min, result.max]).range(isH ? [0, q.svgw] : [q.svgw, 0]);
198
199
  } else {
@@ -241,8 +242,16 @@ async function getDensity(values) {
241
242
  const result = await getDensities({ plot: values });
242
243
  return result.plot;
243
244
  }
244
- async function getDensities(plot2Values) {
245
- const plot2Density = JSON.parse(await run_R("density.R", JSON.stringify({ plot2Values })));
245
+ async function getDensities(plot2Values, useLog = false, logBase = 10) {
246
+ let transformedPlot2Values = {};
247
+ if (useLog) {
248
+ for (const plot in plot2Values) {
249
+ transformedPlot2Values[plot] = plot2Values[plot].filter((v) => v > 0).map((v) => Math.log(v) / Math.log(logBase));
250
+ }
251
+ } else {
252
+ transformedPlot2Values = plot2Values;
253
+ }
254
+ const plot2Density = JSON.parse(await run_R("density.R", JSON.stringify({ plot2Values: transformedPlot2Values })));
246
255
  const densities = {};
247
256
  for (const plot in plot2Density) {
248
257
  const result = plot2Density[plot];
@@ -253,11 +262,12 @@ async function getDensities(plot2Values) {
253
262
  let xMax = -Infinity;
254
263
  for (const [i, x] of Object.entries(result.x)) {
255
264
  const density2 = result.y[i];
256
- xMin = Math.min(xMin, x);
257
- xMax = Math.max(xMax, x);
265
+ const x0 = useLog ? Math.pow(logBase, x) : x;
266
+ xMin = Math.min(xMin, x0);
267
+ xMax = Math.max(xMax, x0);
258
268
  densityMin = Math.min(densityMin, density2);
259
269
  densityMax = Math.max(densityMax, density2);
260
- bins.push({ x0: x, density: density2 });
270
+ bins.push({ x0, density: density2 });
261
271
  }
262
272
  bins.unshift({ x0: xMin, density: densityMin });
263
273
  bins.push({ x0: xMax, density: densityMin });