@sjcrh/proteinpaint-server 2.206.0 → 2.207.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.
@@ -447,11 +447,12 @@ function termdb_test_default() {
447
447
  // .ome.tif extension is required for the JPEG-2000 OME-TIFF reader
448
448
  // in wsi_tile.py open_slide() to engage
449
449
  tiffFileSuffix: "morphology.ome.tif",
450
- nucleusBoundariesFileSuffix: "nucleus_boundaries.csv",
451
- cellBoundariesFileSuffix: "cell_boundaries.csv",
452
- geneExpressionFileSuffix: "gene_expression.h5",
450
+ // consolidated h5ad: the single source for boundaries, annotations
451
+ // and expression (the per-file *FileSuffix fallbacks exist for
452
+ // datasets without one; this fixture's companion CSVs/h5 were removed)
453
+ spatialDataFileSuffix: "spatial.h5ad",
453
454
  // default viewer settings, overridable in the burger menu
454
- geneExpression: "PTPRC",
455
+ cellTypes: true,
455
456
  annotationLevel: 1
456
457
  },
457
458
  trackLst: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjcrh/proteinpaint-server",
3
- "version": "2.206.0",
3
+ "version": "2.207.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",
@@ -57,11 +57,11 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@sjcrh/augen": "2.204.0",
60
- "@sjcrh/proteinpaint-python": "2.204.0",
60
+ "@sjcrh/proteinpaint-python": "2.207.0",
61
61
  "@sjcrh/proteinpaint-r": "2.204.0",
62
- "@sjcrh/proteinpaint-rust": "2.206.0",
63
- "@sjcrh/proteinpaint-shared": "2.206.0",
64
- "@sjcrh/proteinpaint-types": "2.206.0",
62
+ "@sjcrh/proteinpaint-rust": "2.207.0",
63
+ "@sjcrh/proteinpaint-shared": "2.207.0",
64
+ "@sjcrh/proteinpaint-types": "2.207.0",
65
65
  "@types/express": "^5.0.0",
66
66
  "@types/express-session": "^1.18.1",
67
67
  "better-sqlite3": "^12.4.1",
@@ -36,10 +36,14 @@ function init({ genomes }) {
36
36
  async function getBrainImage(query, genomes, plane, index) {
37
37
  const ds = genomes[query.genome].datasets[query.dslabel];
38
38
  const q = ds.queries.NIdata;
39
- const key = query.refKey;
40
- if (q[key].referenceFile && q[key].samples) {
41
- const refFile = path.join(serverconfig.tpmasterdir, q[key].referenceFile);
42
- const dirPath = path.join(serverconfig.tpmasterdir, q[key].samples);
39
+ if (q.checkDataAccess) {
40
+ if (!q.checkDataAccess(query)) throw "no access";
41
+ }
42
+ const ref = q.references[query.refKey];
43
+ if (!ref) throw "invalid refKey";
44
+ if (ref.referenceFile && ref.samples) {
45
+ const refFile = path.join(serverconfig.tpmasterdir, ref.referenceFile);
46
+ const dirPath = path.join(serverconfig.tpmasterdir, ref.samples);
43
47
  const terms = [];
44
48
  const divideByTW = query.divideByTW;
45
49
  const overlayTW = query.overlayTW;
@@ -55,37 +59,43 @@ async function getBrainImage(query, genomes, plane, index) {
55
59
  if (data.error) throw data.error;
56
60
  const divideByCat = {};
57
61
  const uniqueOverlayTwCats = /* @__PURE__ */ new Set();
62
+ const getCategories = (tw, value) => {
63
+ const keys = value.values ? value.values.map((v) => v.key) : [value.key];
64
+ return keys.map((k) => tw.term.values?.[k]?.label || k);
65
+ };
58
66
  for (const sampleName of selectedSampleNames) {
59
67
  const sampleId = ds.sampleName2Id.get(sampleName);
60
68
  const sampleData = data.samples[sampleId];
61
69
  const samplePath = path.join(dirPath, sampleName) + ".nii";
62
- let divideCategory = "default";
70
+ let divideCategories = ["default"];
63
71
  let overlayCategory = "default";
64
72
  if (divideByTW && sampleData) {
65
73
  const value = sampleData[divideByTW.$id];
66
- if (value) divideCategory = divideByTW.term.values?.[value.key]?.label || value.key;
74
+ if (value) divideCategories = getCategories(divideByTW, value);
67
75
  }
68
76
  if (overlayTW && sampleData) {
69
77
  const value = sampleData[overlayTW.$id];
70
78
  if (value) {
71
- overlayCategory = overlayTW.term.values?.[value.key]?.label || value.key;
79
+ overlayCategory = getCategories(overlayTW, value).join(", ");
72
80
  uniqueOverlayTwCats.add(overlayCategory);
73
81
  }
74
82
  }
75
- if (!divideByCat[divideCategory]) divideByCat[divideCategory] = {};
76
- if (!query.legendFilter?.includes(overlayCategory)) {
77
- if (!divideByCat[divideCategory][overlayCategory]) {
78
- let color = overlayTW?.term?.values?.[overlayCategory]?.color;
79
- if (overlayTW && isNumericTerm(overlayTW.term)) {
80
- const bins = data.refs.byTermId[overlayTW.$id].bins;
81
- color = bins.find((b) => b.label == overlayCategory).color;
83
+ for (const divideCategory of divideCategories) {
84
+ if (!divideByCat[divideCategory]) divideByCat[divideCategory] = {};
85
+ if (!query.legendFilter?.includes(overlayCategory)) {
86
+ if (!divideByCat[divideCategory][overlayCategory]) {
87
+ let color = overlayTW?.term?.values?.[overlayCategory]?.color;
88
+ if (overlayTW && isNumericTerm(overlayTW.term)) {
89
+ const bins = data.refs.byTermId[overlayTW.$id].bins;
90
+ color = bins.find((b) => b.label == overlayCategory).color;
91
+ }
92
+ divideByCat[divideCategory][overlayCategory] = {
93
+ samples: [],
94
+ color
95
+ };
82
96
  }
83
- divideByCat[divideCategory][overlayCategory] = {
84
- samples: [],
85
- color
86
- };
97
+ divideByCat[divideCategory][overlayCategory].samples.push(samplePath);
87
98
  }
88
- divideByCat[divideCategory][overlayCategory].samples.push(samplePath);
89
99
  }
90
100
  }
91
101
  const k2c = getColors(uniqueOverlayTwCats.size);
@@ -22,15 +22,19 @@ function init({ genomes }) {
22
22
  async function getBrainImageSamples(query, genomes) {
23
23
  const ds = genomes[query.genome].datasets[query.dslabel];
24
24
  const q = ds.queries.NIdata;
25
- const key = query.refKey;
26
- if (q[key].referenceFile && q[key].samples) {
27
- const dirPath = path.join(serverconfig.tpmasterdir, q[key].samples);
25
+ if (q.checkDataAccess) {
26
+ if (!q.checkDataAccess(query)) throw "no access";
27
+ }
28
+ const ref = q.references[query.refKey];
29
+ if (!ref) throw "invalid refKey";
30
+ if (ref.referenceFile && ref.samples) {
31
+ const dirPath = path.join(serverconfig.tpmasterdir, ref.samples);
28
32
  const files = (await fs.promises.readdir(dirPath, { withFileTypes: true })).filter((f) => f.isFile() && f.name.endsWith(".nii")).map((f) => f.name);
29
33
  let sampleNames = files.map((name) => name.split(".nii")[0]);
30
34
  sampleNames = await filterSampleNamesByAccess(query, ds, sampleNames);
31
35
  if (query.samplesOnly) return sampleNames.map((name) => ({ sample: name }));
32
- if (q[key].sampleColumns) {
33
- const terms = q[key].sampleColumns.map((term) => {
36
+ if (ref.sampleColumns) {
37
+ const terms = ref.sampleColumns.map((term) => {
34
38
  const termjson = ds.cohort.termdb.q.termjsonByOneid(term.termid);
35
39
  return {
36
40
  $id: term.termid,
@@ -46,11 +50,11 @@ async function getBrainImageSamples(query, genomes) {
46
50
  const sid = ds.cohort.termdb.q.sampleName2id(s);
47
51
  const sampleData = data.samples?.[sid];
48
52
  if (sampleData) {
49
- for (const term of q[key].sampleColumns) {
53
+ for (const term of ref.sampleColumns) {
50
54
  const v = sampleData[term.termid];
51
- if (v?.value !== void 0) {
52
- annoForOneS[term.termid] = v.value;
53
- }
55
+ if (!v) continue;
56
+ if (v.values) annoForOneS[term.termid] = v.values.map((x) => x.key).join(", ");
57
+ else if (v.value !== void 0) annoForOneS[term.termid] = v.value;
54
58
  }
55
59
  }
56
60
  samples[s] = annoForOneS;