@genome-spy/app 0.76.0 → 0.77.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 (33) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{agentApi-CzdacisO.js → agentApi-ClsLtELB.js} +7006 -5238
  3. package/dist/agentApi.es.js +3127 -1442
  4. package/dist/agentShared.es.js +20 -20
  5. package/dist/blosc-DL1kZHdE.js +692 -0
  6. package/dist/chunk-INHXZS53-Dx2aFznx.js +13 -0
  7. package/dist/esm-CHVYSGF2.js +1084 -0
  8. package/dist/esm-C_XrKaCY.js +137 -0
  9. package/dist/{esm-Cr7pLUfG.js → esm-CqrZuhTF.js} +1 -1
  10. package/dist/{esm-BWsx1OJ2.js → esm-Cz4iCfzF.js} +1 -1
  11. package/dist/esm-D2-C5ZzN.js +1084 -0
  12. package/dist/{esm-CdIesJ1z.js → esm-Dfo2M18m.js} +1 -1
  13. package/dist/{esm-BH0wx5y-.js → esm-Q6nrd9vJ.js} +1 -1
  14. package/dist/{esm-BLfLaJtE.js → esm-aOLxLL7A.js} +1 -1
  15. package/dist/esm-id9DWBZW.js +137 -0
  16. package/dist/{esm-DHOMWRoL.js → esm-kXhrPIYy.js} +1 -1
  17. package/dist/index.es.js +3768 -4997
  18. package/dist/index.js +420 -357
  19. package/dist/lz4-Csz5aoFA.js +626 -0
  20. package/dist/schema.json +44 -0
  21. package/dist/{viewUtils-C5htqZCm.js → viewUtils-3_xHIxmy.js} +2316 -2171
  22. package/dist/zstd-dJuUp1fl.js +583 -0
  23. package/package.json +4 -4
  24. package/src/agentApi/index.d.ts +24 -0
  25. package/src/sampleView/sampleViewTypes.d.ts +2 -0
  26. package/src/sampleView/state/payloadTypes.d.ts +84 -0
  27. package/src/sampleView/types.d.ts +3 -0
  28. package/src/spec/sampleView.d.ts +58 -0
  29. package/dist/esm-BY4T8YoD.js +0 -142
  30. package/dist/esm-DJUb6vy0.js +0 -1015
  31. package/dist/esm-DRZ5LLNH.js +0 -142
  32. package/dist/esm-PDPkTR1_.js +0 -1015
  33. /package/dist/{parquetRead-BuEN-6yG.js → parquetRead-C33mgLEo.js} +0 -0
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "contributors": [],
9
9
  "license": "MIT",
10
10
  "homepage": "https://genomespy.app/",
11
- "version": "0.76.0",
11
+ "version": "0.77.0",
12
12
  "main": "dist/index.js",
13
13
  "module": "dist/index.es.js",
14
14
  "type": "module",
@@ -70,7 +70,7 @@
70
70
  "@fortawesome/fontawesome-free": "^6.4.2",
71
71
  "@fortawesome/fontawesome-svg-core": "^6.4.2",
72
72
  "@fortawesome/free-solid-svg-icons": "^6.4.2",
73
- "@genome-spy/core": "^0.76.0",
73
+ "@genome-spy/core": "^0.77.0",
74
74
  "@reduxjs/toolkit": "^2.11.0",
75
75
  "d3-color": "^3.1.0",
76
76
  "idb": "^7.1.1",
@@ -82,7 +82,7 @@
82
82
  "zarrita": "^0.6.1"
83
83
  },
84
84
  "devDependencies": {
85
- "@genome-spy/app-agent": "^0.76.0"
85
+ "@genome-spy/app-agent": "^0.77.0"
86
86
  },
87
- "gitHead": "34d821cf5e864972afaa65a3290719e2fdb209c2"
87
+ "gitHead": "2851e22e2069a70d7d02e3ab707b7556573aa17e"
88
88
  }
@@ -23,12 +23,36 @@ import type {
23
23
  } from "../charts/sampleAttributePlotTypes.d.ts";
24
24
  import type { ScaleResolutionApi } from "@genome-spy/core/types/scaleResolutionApi.js";
25
25
  import type UnitView from "@genome-spy/core/view/unitView.js";
26
+
27
+ export interface AgentMetadataSourceIdentifierSummary {
28
+ name: string;
29
+ primary?: boolean;
30
+ caseInsensitive?: boolean;
31
+ stripVersionSuffix?: boolean;
32
+ examples: string[];
33
+ }
34
+
35
+ export interface AgentMetadataSourceSummary {
36
+ sourceId?: string;
37
+ name?: string;
38
+ description?: string;
39
+ attributeDefaults?: {
40
+ dataType?: string;
41
+ description?: string;
42
+ };
43
+ identifiers: AgentMetadataSourceIdentifierSummary[];
44
+ }
45
+
26
46
  export interface AgentApi {
27
47
  /**
28
48
  * Returns the current sample hierarchy used by the agent context.
29
49
  */
30
50
  getSampleHierarchy(): SampleHierarchy | undefined;
31
51
 
52
+ getMetadataSourceSummaries(
53
+ signal?: AbortSignal
54
+ ): Promise<AgentMetadataSourceSummary[]>;
55
+
32
56
  getAttributeInfo(attribute: AttributeIdentifier): AttributeInfo | undefined;
33
57
 
34
58
  /**
@@ -6,6 +6,7 @@ import { Scalar } from "@genome-spy/core/spec/channel.js";
6
6
  import { ComplexDomain, NumericDomain } from "@genome-spy/core/spec/scale.js";
7
7
  import { AggregationSpec, Interval } from "./types.js";
8
8
  import ViewContext from "@genome-spy/core/types/viewContext.js";
9
+ import { SampleLayoutDef } from "@genome-spy/app/spec/sampleView.js";
9
10
  import type {
10
11
  ParamSelector,
11
12
  ViewSelector,
@@ -54,6 +55,7 @@ export interface LocationContext {
54
55
  onLocationUpdate: (arg: { sampleHeight: number }) => void;
55
56
  viewContext: ViewContext;
56
57
  isStickySummaries: () => boolean;
58
+ sampleLayout?: SampleLayoutDef;
57
59
  }
58
60
 
59
61
  export interface BaseSpecifier {
@@ -329,6 +329,90 @@ export interface RemoveGroup {
329
329
  path: string[];
330
330
  }
331
331
 
332
+ export interface RetainGroupsByRank {
333
+ /**
334
+ * One-based grouping level to filter.
335
+ *
336
+ * `1` targets top-level groups under ROOT. `2` targets direct children of
337
+ * level-1 groups, and so on. For top-level categories such as cancer type,
338
+ * use `1`.
339
+ *
340
+ * @minimum 1
341
+ */
342
+ level: number;
343
+
344
+ /**
345
+ * Group-level measure used for ranking.
346
+ *
347
+ * Only `"size"` is supported. Size means group abundance: the number of
348
+ * descendant visible samples in the group.
349
+ */
350
+ measure: "size";
351
+
352
+ /**
353
+ * Number of ranked groups to retain within each ancestor partition.
354
+ *
355
+ * This is k in top-k or bottom-k requests. For example, use `5` to keep
356
+ * the five largest or five smallest groups.
357
+ *
358
+ * @minimum 1
359
+ */
360
+ limit: number;
361
+
362
+ /**
363
+ * Ranking direction.
364
+ *
365
+ * Use `"descending"` for top-k, highest values, largest groups by size, or
366
+ * most abundant groups. Use `"ascending"` for bottom-k, lowest values,
367
+ * smallest groups by size, or least abundant groups.
368
+ */
369
+ order: "descending" | "ascending";
370
+ }
371
+
372
+ export interface RetainGroupsBySize {
373
+ /**
374
+ * One-based grouping level to filter.
375
+ *
376
+ * `1` targets top-level groups under ROOT. `2` targets direct children of
377
+ * level-1 groups, and so on. For top-level categories such as cancer type,
378
+ * use `1`.
379
+ *
380
+ * @minimum 1
381
+ */
382
+ level: number;
383
+
384
+ /**
385
+ * Group-level measure used for thresholding.
386
+ *
387
+ * Only `"size"` is supported. Size means group abundance: the number of
388
+ * descendant visible samples in the group.
389
+ */
390
+ measure: "size";
391
+
392
+ /**
393
+ * Threshold comparison applied as `measure operator operand`.
394
+ */
395
+ operator: ComparisonOperatorType;
396
+
397
+ /**
398
+ * Numeric group-size threshold.
399
+ */
400
+ operand: number;
401
+ }
402
+
403
+ export interface Ungroup {
404
+ /**
405
+ * One-based grouping level to collapse.
406
+ *
407
+ * `1` collapses top-level groups under ROOT and all deeper levels into one
408
+ * flat ROOT sample group. `2` keeps level-1 groups but collapses their
409
+ * children and all deeper levels into sample lists.
410
+ *
411
+ * @minimum 1
412
+ */
413
+ level: number;
414
+ }
415
+
332
416
  /**
333
417
  * Payload for filtering samples by comparing a quantitative attribute
334
418
  * against a numeric operand.
@@ -82,6 +82,9 @@ export interface AttributeInfo {
82
82
  /** More detailed name with optional formatting */
83
83
  title: string | import("lit").TemplateResult;
84
84
 
85
+ /** Plain short label for compact contexts and summaries. */
86
+ shortTitle?: string;
87
+
85
88
  /** Formatted attribute name for context menus (e.g., with selective emphasis). */
86
89
  emphasizedName: string | import("lit").TemplateResult;
87
90
 
@@ -32,6 +32,11 @@ export interface SampleSpec extends Omit<ViewSpecBase, "templates"> {
32
32
  */
33
33
  metadata?: MetadataDef;
34
34
 
35
+ /**
36
+ * Layout settings for sample rows and sample groups.
37
+ */
38
+ sampleLayout?: SampleLayoutDef;
39
+
35
40
  /**
36
41
  * An object defining the view background and outline. The background is
37
42
  * repeated for each group.
@@ -90,6 +95,16 @@ export interface SampleAttributeDef {
90
95
  */
91
96
  barScale?: Scale;
92
97
 
98
+ /**
99
+ * Color used for metadata cells whose value is missing.
100
+ *
101
+ * If `null`, no background is drawn for missing values in this attribute.
102
+ * If omitted, `metadata.missingValueColor` is used. If both are
103
+ * omitted, the default is `null` when `barScale` is configured and
104
+ * `"#f0f0f0"` otherwise.
105
+ */
106
+ missingValueColor?: string | null;
107
+
93
108
  /**
94
109
  * Width of the column in pixels.
95
110
  */
@@ -377,6 +392,16 @@ export interface MetadataDef {
377
392
  */
378
393
  attributeWidth?: number;
379
394
 
395
+ /**
396
+ * Default color for metadata cells whose value is missing.
397
+ *
398
+ * If `null`, missing-value colors are disabled unless overridden by an
399
+ * attribute definition.
400
+ *
401
+ * __Default value:__ `"#f0f0f0"`
402
+ */
403
+ missingValueColor?: string | null;
404
+
380
405
  /**
381
406
  * Spacing between metadata columns in pixels.
382
407
  *
@@ -485,3 +510,36 @@ export interface SampleDef {
485
510
  */
486
511
  labelAlign?: Align;
487
512
  }
513
+
514
+ export interface SampleLayoutDef {
515
+ /**
516
+ * Height of one sample row when the view is expanded for (close-up) inspection.
517
+ * In the birdseye overview, sample rows are automatically scaled to fit the available vertical space.
518
+ *
519
+ * __Default value:__ `35`
520
+ */
521
+ sampleHeight?: number;
522
+
523
+ /**
524
+ * Spacing between sample groups in the fitted layout.
525
+ *
526
+ * __Default value:__ `5`
527
+ */
528
+ groupSpacing?: number;
529
+
530
+ /**
531
+ * Spacing between sample groups in the expanded layout.
532
+ *
533
+ * __Default value:__ `15`
534
+ */
535
+ peekGroupSpacing?: number;
536
+
537
+ /**
538
+ * Fraction of each sample row reserved as spacing between rendered sample contents.
539
+ *
540
+ * Spacing is reduced when rows are too short to render cleanly.
541
+ *
542
+ * __Default value:__ `0.2`
543
+ */
544
+ sampleSpacingFactor?: number;
545
+ }
@@ -1,142 +0,0 @@
1
- import { n as e, t } from "./chunk-CPXzm0be.js";
2
- //#region ../../node_modules/generic-filehandle2/esm/blobFile.js
3
- var n = class {
4
- constructor(e) {
5
- this.blob = e;
6
- }
7
- async read(e, t = 0) {
8
- if (!e) return new Uint8Array();
9
- let n = t, r = n + e, i = this.blob.slice(n, r);
10
- return i.bytes ? i.bytes() : new Uint8Array(await i.arrayBuffer());
11
- }
12
- async readFile(e) {
13
- let t = typeof e == "string" ? e : e?.encoding;
14
- if (t === "utf8") return this.blob.text();
15
- if (t) throw Error(`unsupported encoding: ${t}`);
16
- return this.blob.bytes ? this.blob.bytes() : new Uint8Array(await this.blob.arrayBuffer());
17
- }
18
- async stat() {
19
- return { size: this.blob.size };
20
- }
21
- async close() {}
22
- };
23
- //#endregion
24
- //#region ../../node_modules/generic-filehandle2/esm/remoteFile.js
25
- function r(e) {
26
- return (typeof e == "object" && e && "message" in e ? e.message : `${e}`).replace(/\.$/, "");
27
- }
28
- var i = class {
29
- constructor(e, t = {}) {
30
- this.baseOverrides = {}, this.url = e;
31
- let n = t.fetch || globalThis.fetch.bind(globalThis);
32
- t.overrides && (this.baseOverrides = t.overrides), this.fetchImplementation = n;
33
- }
34
- async fetch(e, t) {
35
- let n = (t) => Error(`${r(t)} fetching ${e}`, { cause: t }), i;
36
- try {
37
- i = await this.fetchImplementation(e, t);
38
- } catch (r) {
39
- if (`${r}`.includes("Failed to fetch")) {
40
- console.warn(`generic-filehandle: refetching ${e} to attempt to work around chrome CORS header caching bug`);
41
- try {
42
- i = await this.fetchImplementation(e, {
43
- ...t,
44
- cache: "reload"
45
- });
46
- } catch (e) {
47
- throw n(e);
48
- }
49
- } else throw n(r);
50
- }
51
- return i;
52
- }
53
- async read(e, t, n = {}) {
54
- if (e === 0) return new Uint8Array();
55
- let { headers: r = {}, signal: i, overrides: a = {} } = n;
56
- e < Infinity ? r.range = `bytes=${t}-${t + e - 1}` : e === Infinity && t !== 0 && (r.range = `bytes=${t}-`);
57
- let o = await this.fetch(this.url, {
58
- ...this.baseOverrides,
59
- ...a,
60
- headers: {
61
- ...this.baseOverrides.headers,
62
- ...a.headers,
63
- ...r
64
- },
65
- method: "GET",
66
- redirect: "follow",
67
- mode: "cors",
68
- signal: i
69
- });
70
- if (!o.ok) throw Error(`HTTP ${o.status} fetching ${this.url}`);
71
- if (o.status === 200 && t === 0 || o.status === 206) {
72
- let t = o.headers.get("content-range"), n = /\/(\d+)$/.exec(t || "");
73
- n?.[1] && (this._stat = { size: parseInt(n[1], 10) });
74
- let r = o.bytes ? await o.bytes() : new Uint8Array(await o.arrayBuffer());
75
- return r.byteLength <= e ? r : r.subarray(0, e);
76
- }
77
- throw Error(o.status === 200 ? `${this.url} fetch returned status 200, expected 206` : `HTTP ${o.status} fetching ${this.url}`);
78
- }
79
- async readFile(e = {}) {
80
- let t, n;
81
- if (typeof e == "string") t = e, n = {};
82
- else {
83
- t = e.encoding;
84
- let { encoding: r, ...i } = e;
85
- n = i;
86
- }
87
- let { headers: r = {}, signal: i, overrides: a = {} } = n, o = await this.fetch(this.url, {
88
- ...this.baseOverrides,
89
- ...a,
90
- headers: {
91
- ...this.baseOverrides.headers,
92
- ...a.headers,
93
- ...r
94
- },
95
- method: "GET",
96
- redirect: "follow",
97
- mode: "cors",
98
- signal: i
99
- });
100
- if (!o.ok) throw Error(`HTTP ${o.status} fetching ${this.url}`);
101
- if (t === "utf8") return o.text();
102
- if (t) throw Error(`unsupported encoding: ${t}`);
103
- return o.bytes ? o.bytes() : new Uint8Array(await o.arrayBuffer());
104
- }
105
- async stat() {
106
- if (!this._stat && (await this.read(10, 0), !this._stat)) throw Error(`unable to determine size of file at ${this.url}`);
107
- return this._stat;
108
- }
109
- async close() {}
110
- }, a = (/* @__PURE__ */ t(((e, t) => {
111
- t.exports = {};
112
- })))(), o = class {
113
- constructor(e, t = {}) {
114
- this.filename = e;
115
- }
116
- async read(e, t = 0) {
117
- if (e === 0) return new Uint8Array();
118
- let n = new Uint8Array(e), r;
119
- try {
120
- r = await (0, a.open)(this.filename, "r");
121
- let i = await r.read(n, 0, e, t);
122
- return i.buffer.subarray(0, i.bytesRead);
123
- } finally {
124
- if (r) try {
125
- await r.close();
126
- } catch {}
127
- }
128
- }
129
- async readFile(e) {
130
- return (0, a.readFile)(this.filename, e);
131
- }
132
- async stat() {
133
- return (0, a.stat)(this.filename);
134
- }
135
- async close() {}
136
- }, s = /* @__PURE__ */ e({
137
- BlobFile: () => n,
138
- LocalFile: () => o,
139
- RemoteFile: () => i
140
- });
141
- //#endregion
142
- export { o as n, i as r, s as t };