gosling.js 2.0.0-alpha.7 → 2.0.0-alpha.8

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 (30) hide show
  1. package/dist/demo/gosling-component.d.ts.map +1 -1
  2. package/dist/demo/renderer/dataFetcher.d.ts.map +1 -1
  3. package/dist/demo/renderer/main.d.ts.map +1 -1
  4. package/dist/demo/track-def/main.d.ts +4 -1
  5. package/dist/demo/track-def/main.d.ts.map +1 -1
  6. package/dist/demo/track-def/types.d.ts +13 -3
  7. package/dist/demo/track-def/types.d.ts.map +1 -1
  8. package/dist/{exported-utils-b3cf08ff.js → exported-utils-9e651c40.js} +65 -1
  9. package/dist/exported-utils-9e651c40.js.map +1 -0
  10. package/dist/gosling.js +1162 -83
  11. package/dist/gosling.js.map +1 -1
  12. package/dist/src/compiler/_normalize-3d-spec.d.ts +8 -0
  13. package/dist/src/compiler/_normalize-3d-spec.d.ts.map +1 -0
  14. package/dist/src/compiler/spec-preprocess.d.ts.map +1 -1
  15. package/dist/src/core/utils/assembly.d.ts.map +1 -1
  16. package/dist/src/core/utils/assert.d.ts +17 -0
  17. package/dist/src/core/utils/assert.d.ts.map +1 -0
  18. package/dist/src/core/utils/chrom-size.d.ts +18 -0
  19. package/dist/src/core/utils/chrom-size.d.ts.map +1 -1
  20. package/dist/src/core/utils/data-transform.d.ts +10 -1
  21. package/dist/src/core/utils/data-transform.d.ts.map +1 -1
  22. package/dist/src/gosling-schema/gosling.schema.d.ts +41 -4
  23. package/dist/src/gosling-schema/gosling.schema.d.ts.map +1 -1
  24. package/dist/src/tracks/gosling-track/gosling-track.d.ts +1 -1
  25. package/dist/src/tracks/gosling-track/gosling-track.d.ts.map +1 -1
  26. package/dist/src/tracks/spatial-track/spatial-track.d.ts +22 -0
  27. package/dist/src/tracks/spatial-track/spatial-track.d.ts.map +1 -0
  28. package/dist/utils.js +1 -1
  29. package/package.json +4 -2
  30. package/dist/exported-utils-b3cf08ff.js.map +0 -1
package/dist/gosling.js CHANGED
@@ -35,7 +35,7 @@ import { scaleLinear, scaleLog, scaleQuantile, scaleSequential, scaleOrdinal, sc
35
35
  import { drag } from "d3-drag";
36
36
  import { sampleSize, isEqual, uniqBy } from "lodash-es";
37
37
  import { interpolateViridis } from "d3-scale-chromatic";
38
- import { A as Ajv, r as resolveSuperposedTracks, I as IsChannelDeep, t as traverseTracks, a as IsTemplateTrack, D as DEWFAULT_TITLE_PADDING_ON_TOP_AND_BOTTOM, b as traverseTracksAndViews, c as traverseViewArrangements, d as DEFAULT_AXIS_SIZE, e as Is2DTrack, f as DEFAULT_VIEW_SPACING, g as DEFAULT_INNER_RADIUS_PROP, h as IsOverlaidTrack, i as IsXAxis, j as IsYAxis, k as DEFAULT_CIRCULAR_VIEW_PADDING, u as uuid, l as traverseToFixSpecDownstream, m as absToChr, n as colorToHex, o as getTextStyle, p as computeChromSizes, q as cartesianToPolar, s as IsDummyTrack, v as getHiGlassColorRange, R as RADIAN_GAP, w as valueToRadian, x as pointsToDegree, y as commonjsGlobal, z as RemoteFile, B as chrToAbs, C as IsOneOfFilter, E as IsRangeFilter, F as IsIncludeFilter, G as getChannelKeysByAggregateFnc, H as getChannelKeysByType, J as sanitizeChrName, K as filterUsingGenoPos, L as IsDataDeepTileset, M as IsDomainChr, N as IsDomainInterval, O as IsDomainChrInterval, S as SUPPORTED_CHANNELS, P as IsChannelValue, Q as getValueUsingChannel, T as rectProperty, U as pointProperty, V as barProperty, W as IsStackedChannel, X as IsDomainArray, Y as PREDEFINED_COLOR_STR_MAP, Z as IsRangeArray, _ as isTabularDataFetcher, $ as drawPreEmbellishment, a0 as drawMark, a1 as drawPostEmbellishment, a2 as getRelativeGenomicPosition, a3 as hasDataTransform, a4 as IsMouseEventsDeep, a5 as flatArrayToPairArray, a6 as IsSingleView, a7 as IsMultipleViews, a8 as GenomicPositionHelper } from "./exported-utils-b3cf08ff.js";
38
+ import { A as Ajv, r as resolveSuperposedTracks, I as IsChannelDeep, t as traverseTracks, a as IsTemplateTrack, D as DEWFAULT_TITLE_PADDING_ON_TOP_AND_BOTTOM, b as traverseTracksAndViews, c as traverseViewArrangements, d as DEFAULT_AXIS_SIZE, e as Is2DTrack, f as DEFAULT_VIEW_SPACING, g as DEFAULT_INNER_RADIUS_PROP, h as IsOverlaidTrack, i as IsXAxis, j as IsYAxis, k as DEFAULT_CIRCULAR_VIEW_PADDING, u as uuid, l as traverseToFixSpecDownstream, m as absToChr, n as colorToHex, o as getTextStyle, p as computeChromSizes, q as cartesianToPolar, s as IsDummyTrack, v as getHiGlassColorRange, R as RADIAN_GAP, w as valueToRadian, x as pointsToDegree, y as commonjsGlobal, z as RemoteFile, B as chrToAbs, C as IsOneOfFilter, E as IsRangeFilter, F as IsIncludeFilter, G as getChannelKeysByAggregateFnc, H as getChannelKeysByType, J as sanitizeChrName, K as filterUsingGenoPos, L as IsDataDeepTileset, M as IsDomainChr, N as IsDomainInterval, O as IsDomainChrInterval, S as SUPPORTED_CHANNELS, P as IsChannelValue, Q as getValueUsingChannel, T as rectProperty, U as pointProperty, V as barProperty, W as IsStackedChannel, X as IsDomainArray, Y as PREDEFINED_COLOR_STR_MAP, Z as IsRangeArray, _ as isTabularDataFetcher, $ as drawPreEmbellishment, a0 as drawMark, a1 as drawPostEmbellishment, a2 as getRelativeGenomicPosition, a3 as hasDataTransform, a4 as IsMouseEventsDeep, a5 as flatArrayToPairArray, a6 as IsSingleView, a7 as IsMultipleViews, a8 as GenomicPositionHelper } from "./exported-utils-9e651c40.js";
39
39
  import React, { useState, useImperativeHandle, useEffect } from "react";
40
40
  import { format, precisionPrefix, formatPrefix } from "d3-format";
41
41
  import slugid from "slugid";
@@ -54,8 +54,10 @@ import { dsvFormat } from "d3-dsv";
54
54
  import { createNanoEvents } from "nanoevents";
55
55
  import PubSub$1 from "pubsub-js";
56
56
  import { zoom, ZoomTransform } from "d3-zoom";
57
+ import * as uchi from "uchimata";
58
+ import { tableFromArrays, tableToIPC, tableFromIPC, Type } from "@uwdata/flechette";
57
59
  const name = "gosling.js";
58
- const version = "2.0.0-alpha.7";
60
+ const version = "2.0.0-alpha.8";
59
61
  const $ref$1 = "#/definitions/GoslingSpec";
60
62
  const $schema$1 = "http://json-schema.org/draft-07/schema#";
61
63
  const definitions$1 = {
@@ -99,6 +101,10 @@ const definitions$1 = {
99
101
  "const": "mm9",
100
102
  type: "string"
101
103
  },
104
+ {
105
+ "const": "sacCer3",
106
+ type: "string"
107
+ },
102
108
  {
103
109
  "const": "unknown",
104
110
  type: "string"
@@ -621,6 +627,9 @@ const definitions$1 = {
621
627
  {
622
628
  $ref: "#/definitions/FilterTransform"
623
629
  },
630
+ {
631
+ $ref: "#/definitions/JoinTransform"
632
+ },
624
633
  {
625
634
  $ref: "#/definitions/StrConcatTransform"
626
635
  },
@@ -1213,6 +1222,16 @@ const definitions$1 = {
1213
1222
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
1214
1223
  type: "string"
1215
1224
  },
1225
+ locus: {
1226
+ anyOf: [
1227
+ {
1228
+ $ref: "#/definitions/X"
1229
+ },
1230
+ {
1231
+ $ref: "#/definitions/ChannelValue"
1232
+ }
1233
+ ]
1234
+ },
1216
1235
  mark: {
1217
1236
  $ref: "#/definitions/Mark"
1218
1237
  },
@@ -1366,6 +1385,16 @@ const definitions$1 = {
1366
1385
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
1367
1386
  type: "string"
1368
1387
  },
1388
+ locus: {
1389
+ anyOf: [
1390
+ {
1391
+ $ref: "#/definitions/X"
1392
+ },
1393
+ {
1394
+ $ref: "#/definitions/ChannelValue"
1395
+ }
1396
+ ]
1397
+ },
1369
1398
  mark: {
1370
1399
  $ref: "#/definitions/Mark"
1371
1400
  },
@@ -1424,6 +1453,34 @@ const definitions$1 = {
1424
1453
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
1425
1454
  type: "number"
1426
1455
  },
1456
+ spatial: {
1457
+ additionalProperties: false,
1458
+ properties: {
1459
+ chr: {
1460
+ type: "string"
1461
+ },
1462
+ coord: {
1463
+ type: "string"
1464
+ },
1465
+ x: {
1466
+ type: "string"
1467
+ },
1468
+ y: {
1469
+ type: "string"
1470
+ },
1471
+ z: {
1472
+ type: "string"
1473
+ }
1474
+ },
1475
+ required: [
1476
+ "x",
1477
+ "y",
1478
+ "z",
1479
+ "chr",
1480
+ "coord"
1481
+ ],
1482
+ type: "object"
1483
+ },
1427
1484
  startAngle: {
1428
1485
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
1429
1486
  type: "number"
@@ -1674,6 +1731,34 @@ const definitions$1 = {
1674
1731
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
1675
1732
  type: "number"
1676
1733
  },
1734
+ spatial: {
1735
+ additionalProperties: false,
1736
+ properties: {
1737
+ chr: {
1738
+ type: "string"
1739
+ },
1740
+ coord: {
1741
+ type: "string"
1742
+ },
1743
+ x: {
1744
+ type: "string"
1745
+ },
1746
+ y: {
1747
+ type: "string"
1748
+ },
1749
+ z: {
1750
+ type: "string"
1751
+ }
1752
+ },
1753
+ required: [
1754
+ "x",
1755
+ "y",
1756
+ "z",
1757
+ "chr",
1758
+ "coord"
1759
+ ],
1760
+ type: "object"
1761
+ },
1677
1762
  startAngle: {
1678
1763
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
1679
1764
  type: "number"
@@ -1983,6 +2068,16 @@ const definitions$1 = {
1983
2068
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
1984
2069
  type: "string"
1985
2070
  },
2071
+ locus: {
2072
+ anyOf: [
2073
+ {
2074
+ $ref: "#/definitions/X"
2075
+ },
2076
+ {
2077
+ $ref: "#/definitions/ChannelValue"
2078
+ }
2079
+ ]
2080
+ },
1986
2081
  mark: {
1987
2082
  $ref: "#/definitions/Mark"
1988
2083
  },
@@ -2136,6 +2231,16 @@ const definitions$1 = {
2136
2231
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
2137
2232
  type: "string"
2138
2233
  },
2234
+ locus: {
2235
+ anyOf: [
2236
+ {
2237
+ $ref: "#/definitions/X"
2238
+ },
2239
+ {
2240
+ $ref: "#/definitions/ChannelValue"
2241
+ }
2242
+ ]
2243
+ },
2139
2244
  mark: {
2140
2245
  $ref: "#/definitions/Mark"
2141
2246
  },
@@ -2194,6 +2299,34 @@ const definitions$1 = {
2194
2299
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
2195
2300
  type: "number"
2196
2301
  },
2302
+ spatial: {
2303
+ additionalProperties: false,
2304
+ properties: {
2305
+ chr: {
2306
+ type: "string"
2307
+ },
2308
+ coord: {
2309
+ type: "string"
2310
+ },
2311
+ x: {
2312
+ type: "string"
2313
+ },
2314
+ y: {
2315
+ type: "string"
2316
+ },
2317
+ z: {
2318
+ type: "string"
2319
+ }
2320
+ },
2321
+ required: [
2322
+ "x",
2323
+ "y",
2324
+ "z",
2325
+ "chr",
2326
+ "coord"
2327
+ ],
2328
+ type: "object"
2329
+ },
2197
2330
  startAngle: {
2198
2331
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
2199
2332
  type: "number"
@@ -2444,6 +2577,34 @@ const definitions$1 = {
2444
2577
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
2445
2578
  type: "number"
2446
2579
  },
2580
+ spatial: {
2581
+ additionalProperties: false,
2582
+ properties: {
2583
+ chr: {
2584
+ type: "string"
2585
+ },
2586
+ coord: {
2587
+ type: "string"
2588
+ },
2589
+ x: {
2590
+ type: "string"
2591
+ },
2592
+ y: {
2593
+ type: "string"
2594
+ },
2595
+ z: {
2596
+ type: "string"
2597
+ }
2598
+ },
2599
+ required: [
2600
+ "x",
2601
+ "y",
2602
+ "z",
2603
+ "chr",
2604
+ "coord"
2605
+ ],
2606
+ type: "object"
2607
+ },
2447
2608
  startAngle: {
2448
2609
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
2449
2610
  type: "number"
@@ -2810,6 +2971,16 @@ const definitions$1 = {
2810
2971
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
2811
2972
  type: "string"
2812
2973
  },
2974
+ locus: {
2975
+ anyOf: [
2976
+ {
2977
+ $ref: "#/definitions/X"
2978
+ },
2979
+ {
2980
+ $ref: "#/definitions/ChannelValue"
2981
+ }
2982
+ ]
2983
+ },
2813
2984
  mark: {
2814
2985
  $ref: "#/definitions/Mark"
2815
2986
  },
@@ -2868,6 +3039,34 @@ const definitions$1 = {
2868
3039
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
2869
3040
  type: "number"
2870
3041
  },
3042
+ spatial: {
3043
+ additionalProperties: false,
3044
+ properties: {
3045
+ chr: {
3046
+ type: "string"
3047
+ },
3048
+ coord: {
3049
+ type: "string"
3050
+ },
3051
+ x: {
3052
+ type: "string"
3053
+ },
3054
+ y: {
3055
+ type: "string"
3056
+ },
3057
+ z: {
3058
+ type: "string"
3059
+ }
3060
+ },
3061
+ required: [
3062
+ "x",
3063
+ "y",
3064
+ "z",
3065
+ "chr",
3066
+ "coord"
3067
+ ],
3068
+ type: "object"
3069
+ },
2871
3070
  startAngle: {
2872
3071
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
2873
3072
  type: "number"
@@ -3463,6 +3662,59 @@ const definitions$1 = {
3463
3662
  ],
3464
3663
  type: "object"
3465
3664
  },
3665
+ JoinTransform: {
3666
+ additionalProperties: false,
3667
+ description: "Join new data to the existing data. The data will be combined based on the overlap of genomic positions. The data will join _right_ to the new data (e.g., BigWig --> 3D Model).",
3668
+ properties: {
3669
+ from: {
3670
+ additionalProperties: false,
3671
+ description: "The new data to be combined, e.g., 3D Model",
3672
+ properties: {
3673
+ chromosomeField: {
3674
+ type: "string"
3675
+ },
3676
+ genomicField: {
3677
+ type: "string"
3678
+ },
3679
+ url: {
3680
+ type: "string"
3681
+ }
3682
+ },
3683
+ required: [
3684
+ "url",
3685
+ "chromosomeField",
3686
+ "genomicField"
3687
+ ],
3688
+ type: "object"
3689
+ },
3690
+ to: {
3691
+ additionalProperties: false,
3692
+ description: "The existing data to be updated, e.g., BigWig",
3693
+ properties: {
3694
+ endField: {
3695
+ type: "string"
3696
+ },
3697
+ startField: {
3698
+ type: "string"
3699
+ }
3700
+ },
3701
+ required: [
3702
+ "startField"
3703
+ ],
3704
+ type: "object"
3705
+ },
3706
+ type: {
3707
+ "const": "join",
3708
+ type: "string"
3709
+ }
3710
+ },
3711
+ required: [
3712
+ "type",
3713
+ "to",
3714
+ "from"
3715
+ ],
3716
+ type: "object"
3717
+ },
3466
3718
  JsonData: {
3467
3719
  additionalProperties: false,
3468
3720
  description: "The JSON data format allows users to include data directly in the Gosling's JSON specification.",
@@ -3559,11 +3811,71 @@ const definitions$1 = {
3559
3811
  type: "object"
3560
3812
  },
3561
3813
  Layout: {
3562
- "enum": [
3563
- "linear",
3564
- "circular"
3814
+ anyOf: [
3815
+ {
3816
+ "const": "linear",
3817
+ type: "string"
3818
+ },
3819
+ {
3820
+ "const": "circular",
3821
+ type: "string"
3822
+ },
3823
+ {
3824
+ "const": "spatial",
3825
+ type: "string"
3826
+ },
3827
+ {
3828
+ $ref: "#/definitions/LayoutSpatial"
3829
+ }
3830
+ ]
3831
+ },
3832
+ LayoutSpatial: {
3833
+ additionalProperties: false,
3834
+ properties: {
3835
+ model: {
3836
+ additionalProperties: false,
3837
+ properties: {
3838
+ chromosome: {
3839
+ type: "string"
3840
+ },
3841
+ position: {
3842
+ type: "string"
3843
+ },
3844
+ type: {
3845
+ "const": "csv",
3846
+ type: "string"
3847
+ },
3848
+ url: {
3849
+ type: "string"
3850
+ },
3851
+ xyz: {
3852
+ items: {
3853
+ type: "string"
3854
+ },
3855
+ maxItems: 3,
3856
+ minItems: 3,
3857
+ type: "array"
3858
+ }
3859
+ },
3860
+ required: [
3861
+ "type",
3862
+ "url",
3863
+ "xyz",
3864
+ "chromosome",
3865
+ "position"
3866
+ ],
3867
+ type: "object"
3868
+ },
3869
+ type: {
3870
+ "const": "spatial",
3871
+ type: "string"
3872
+ }
3873
+ },
3874
+ required: [
3875
+ "type",
3876
+ "model"
3565
3877
  ],
3566
- type: "string"
3878
+ type: "object"
3567
3879
  },
3568
3880
  LogBase: {
3569
3881
  anyOf: [
@@ -3633,7 +3945,10 @@ const definitions$1 = {
3633
3945
  "triangleRight",
3634
3946
  "triangleBottom",
3635
3947
  "brush",
3636
- "_header"
3948
+ "_header",
3949
+ "sphere",
3950
+ "box",
3951
+ "octahedron"
3637
3952
  ],
3638
3953
  type: "string"
3639
3954
  },
@@ -4044,6 +4359,16 @@ const definitions$1 = {
4044
4359
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
4045
4360
  type: "string"
4046
4361
  },
4362
+ locus: {
4363
+ anyOf: [
4364
+ {
4365
+ $ref: "#/definitions/X"
4366
+ },
4367
+ {
4368
+ $ref: "#/definitions/ChannelValue"
4369
+ }
4370
+ ]
4371
+ },
4047
4372
  mark: {
4048
4373
  $ref: "#/definitions/Mark"
4049
4374
  },
@@ -4102,6 +4427,34 @@ const definitions$1 = {
4102
4427
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
4103
4428
  type: "number"
4104
4429
  },
4430
+ spatial: {
4431
+ additionalProperties: false,
4432
+ properties: {
4433
+ chr: {
4434
+ type: "string"
4435
+ },
4436
+ coord: {
4437
+ type: "string"
4438
+ },
4439
+ x: {
4440
+ type: "string"
4441
+ },
4442
+ y: {
4443
+ type: "string"
4444
+ },
4445
+ z: {
4446
+ type: "string"
4447
+ }
4448
+ },
4449
+ required: [
4450
+ "x",
4451
+ "y",
4452
+ "z",
4453
+ "chr",
4454
+ "coord"
4455
+ ],
4456
+ type: "object"
4457
+ },
4105
4458
  startAngle: {
4106
4459
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
4107
4460
  type: "number"
@@ -4371,6 +4724,16 @@ const definitions$1 = {
4371
4724
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
4372
4725
  type: "string"
4373
4726
  },
4727
+ locus: {
4728
+ anyOf: [
4729
+ {
4730
+ $ref: "#/definitions/X"
4731
+ },
4732
+ {
4733
+ $ref: "#/definitions/ChannelValue"
4734
+ }
4735
+ ]
4736
+ },
4374
4737
  mark: {
4375
4738
  $ref: "#/definitions/Mark"
4376
4739
  },
@@ -4429,6 +4792,34 @@ const definitions$1 = {
4429
4792
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
4430
4793
  type: "number"
4431
4794
  },
4795
+ spatial: {
4796
+ additionalProperties: false,
4797
+ properties: {
4798
+ chr: {
4799
+ type: "string"
4800
+ },
4801
+ coord: {
4802
+ type: "string"
4803
+ },
4804
+ x: {
4805
+ type: "string"
4806
+ },
4807
+ y: {
4808
+ type: "string"
4809
+ },
4810
+ z: {
4811
+ type: "string"
4812
+ }
4813
+ },
4814
+ required: [
4815
+ "x",
4816
+ "y",
4817
+ "z",
4818
+ "chr",
4819
+ "coord"
4820
+ ],
4821
+ type: "object"
4822
+ },
4432
4823
  startAngle: {
4433
4824
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
4434
4825
  type: "number"
@@ -4728,6 +5119,16 @@ const definitions$1 = {
4728
5119
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
4729
5120
  type: "string"
4730
5121
  },
5122
+ locus: {
5123
+ anyOf: [
5124
+ {
5125
+ $ref: "#/definitions/X"
5126
+ },
5127
+ {
5128
+ $ref: "#/definitions/ChannelValue"
5129
+ }
5130
+ ]
5131
+ },
4731
5132
  mark: {
4732
5133
  $ref: "#/definitions/Mark"
4733
5134
  },
@@ -4786,6 +5187,34 @@ const definitions$1 = {
4786
5187
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
4787
5188
  type: "number"
4788
5189
  },
5190
+ spatial: {
5191
+ additionalProperties: false,
5192
+ properties: {
5193
+ chr: {
5194
+ type: "string"
5195
+ },
5196
+ coord: {
5197
+ type: "string"
5198
+ },
5199
+ x: {
5200
+ type: "string"
5201
+ },
5202
+ y: {
5203
+ type: "string"
5204
+ },
5205
+ z: {
5206
+ type: "string"
5207
+ }
5208
+ },
5209
+ required: [
5210
+ "x",
5211
+ "y",
5212
+ "z",
5213
+ "chr",
5214
+ "coord"
5215
+ ],
5216
+ type: "object"
5217
+ },
4789
5218
  startAngle: {
4790
5219
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
4791
5220
  type: "number"
@@ -5095,6 +5524,16 @@ const definitions$1 = {
5095
5524
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
5096
5525
  type: "string"
5097
5526
  },
5527
+ locus: {
5528
+ anyOf: [
5529
+ {
5530
+ $ref: "#/definitions/X"
5531
+ },
5532
+ {
5533
+ $ref: "#/definitions/ChannelValue"
5534
+ }
5535
+ ]
5536
+ },
5098
5537
  mark: {
5099
5538
  $ref: "#/definitions/Mark"
5100
5539
  },
@@ -5153,6 +5592,34 @@ const definitions$1 = {
5153
5592
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
5154
5593
  type: "number"
5155
5594
  },
5595
+ spatial: {
5596
+ additionalProperties: false,
5597
+ properties: {
5598
+ chr: {
5599
+ type: "string"
5600
+ },
5601
+ coord: {
5602
+ type: "string"
5603
+ },
5604
+ x: {
5605
+ type: "string"
5606
+ },
5607
+ y: {
5608
+ type: "string"
5609
+ },
5610
+ z: {
5611
+ type: "string"
5612
+ }
5613
+ },
5614
+ required: [
5615
+ "x",
5616
+ "y",
5617
+ "z",
5618
+ "chr",
5619
+ "coord"
5620
+ ],
5621
+ type: "object"
5622
+ },
5156
5623
  startAngle: {
5157
5624
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
5158
5625
  type: "number"
@@ -5448,6 +5915,16 @@ const definitions$1 = {
5448
5915
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
5449
5916
  type: "string"
5450
5917
  },
5918
+ locus: {
5919
+ anyOf: [
5920
+ {
5921
+ $ref: "#/definitions/X"
5922
+ },
5923
+ {
5924
+ $ref: "#/definitions/ChannelValue"
5925
+ }
5926
+ ]
5927
+ },
5451
5928
  mark: {
5452
5929
  $ref: "#/definitions/Mark"
5453
5930
  },
@@ -5506,6 +5983,34 @@ const definitions$1 = {
5506
5983
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
5507
5984
  type: "number"
5508
5985
  },
5986
+ spatial: {
5987
+ additionalProperties: false,
5988
+ properties: {
5989
+ chr: {
5990
+ type: "string"
5991
+ },
5992
+ coord: {
5993
+ type: "string"
5994
+ },
5995
+ x: {
5996
+ type: "string"
5997
+ },
5998
+ y: {
5999
+ type: "string"
6000
+ },
6001
+ z: {
6002
+ type: "string"
6003
+ }
6004
+ },
6005
+ required: [
6006
+ "x",
6007
+ "y",
6008
+ "z",
6009
+ "chr",
6010
+ "coord"
6011
+ ],
6012
+ type: "object"
6013
+ },
5509
6014
  startAngle: {
5510
6015
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
5511
6016
  type: "number"
@@ -5988,6 +6493,16 @@ const definitions$1 = {
5988
6493
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
5989
6494
  type: "string"
5990
6495
  },
6496
+ locus: {
6497
+ anyOf: [
6498
+ {
6499
+ $ref: "#/definitions/X"
6500
+ },
6501
+ {
6502
+ $ref: "#/definitions/ChannelValue"
6503
+ }
6504
+ ]
6505
+ },
5991
6506
  mark: {
5992
6507
  $ref: "#/definitions/Mark"
5993
6508
  },
@@ -6046,6 +6561,34 @@ const definitions$1 = {
6046
6561
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
6047
6562
  type: "number"
6048
6563
  },
6564
+ spatial: {
6565
+ additionalProperties: false,
6566
+ properties: {
6567
+ chr: {
6568
+ type: "string"
6569
+ },
6570
+ coord: {
6571
+ type: "string"
6572
+ },
6573
+ x: {
6574
+ type: "string"
6575
+ },
6576
+ y: {
6577
+ type: "string"
6578
+ },
6579
+ z: {
6580
+ type: "string"
6581
+ }
6582
+ },
6583
+ required: [
6584
+ "x",
6585
+ "y",
6586
+ "z",
6587
+ "chr",
6588
+ "coord"
6589
+ ],
6590
+ type: "object"
6591
+ },
6049
6592
  startAngle: {
6050
6593
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
6051
6594
  type: "number"
@@ -6348,6 +6891,16 @@ const definitions$1 = {
6348
6891
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
6349
6892
  type: "string"
6350
6893
  },
6894
+ locus: {
6895
+ anyOf: [
6896
+ {
6897
+ $ref: "#/definitions/X"
6898
+ },
6899
+ {
6900
+ $ref: "#/definitions/ChannelValue"
6901
+ }
6902
+ ]
6903
+ },
6351
6904
  mark: {
6352
6905
  $ref: "#/definitions/Mark"
6353
6906
  },
@@ -6497,6 +7050,16 @@ const definitions$1 = {
6497
7050
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
6498
7051
  type: "string"
6499
7052
  },
7053
+ locus: {
7054
+ anyOf: [
7055
+ {
7056
+ $ref: "#/definitions/X"
7057
+ },
7058
+ {
7059
+ $ref: "#/definitions/ChannelValue"
7060
+ }
7061
+ ]
7062
+ },
6500
7063
  mark: {
6501
7064
  $ref: "#/definitions/Mark"
6502
7065
  },
@@ -6555,6 +7118,34 @@ const definitions$1 = {
6555
7118
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
6556
7119
  type: "number"
6557
7120
  },
7121
+ spatial: {
7122
+ additionalProperties: false,
7123
+ properties: {
7124
+ chr: {
7125
+ type: "string"
7126
+ },
7127
+ coord: {
7128
+ type: "string"
7129
+ },
7130
+ x: {
7131
+ type: "string"
7132
+ },
7133
+ y: {
7134
+ type: "string"
7135
+ },
7136
+ z: {
7137
+ type: "string"
7138
+ }
7139
+ },
7140
+ required: [
7141
+ "x",
7142
+ "y",
7143
+ "z",
7144
+ "chr",
7145
+ "coord"
7146
+ ],
7147
+ type: "object"
7148
+ },
6558
7149
  startAngle: {
6559
7150
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
6560
7151
  type: "number"
@@ -6805,6 +7396,34 @@ const definitions$1 = {
6805
7396
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
6806
7397
  type: "number"
6807
7398
  },
7399
+ spatial: {
7400
+ additionalProperties: false,
7401
+ properties: {
7402
+ chr: {
7403
+ type: "string"
7404
+ },
7405
+ coord: {
7406
+ type: "string"
7407
+ },
7408
+ x: {
7409
+ type: "string"
7410
+ },
7411
+ y: {
7412
+ type: "string"
7413
+ },
7414
+ z: {
7415
+ type: "string"
7416
+ }
7417
+ },
7418
+ required: [
7419
+ "x",
7420
+ "y",
7421
+ "z",
7422
+ "chr",
7423
+ "coord"
7424
+ ],
7425
+ type: "object"
7426
+ },
6808
7427
  startAngle: {
6809
7428
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
6810
7429
  type: "number"
@@ -7111,6 +7730,16 @@ const definitions$1 = {
7111
7730
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
7112
7731
  type: "string"
7113
7732
  },
7733
+ locus: {
7734
+ anyOf: [
7735
+ {
7736
+ $ref: "#/definitions/X"
7737
+ },
7738
+ {
7739
+ $ref: "#/definitions/ChannelValue"
7740
+ }
7741
+ ]
7742
+ },
7114
7743
  mark: {
7115
7744
  $ref: "#/definitions/Mark"
7116
7745
  },
@@ -7260,6 +7889,16 @@ const definitions$1 = {
7260
7889
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
7261
7890
  type: "string"
7262
7891
  },
7892
+ locus: {
7893
+ anyOf: [
7894
+ {
7895
+ $ref: "#/definitions/X"
7896
+ },
7897
+ {
7898
+ $ref: "#/definitions/ChannelValue"
7899
+ }
7900
+ ]
7901
+ },
7263
7902
  mark: {
7264
7903
  $ref: "#/definitions/Mark"
7265
7904
  },
@@ -7318,6 +7957,34 @@ const definitions$1 = {
7318
7957
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
7319
7958
  type: "number"
7320
7959
  },
7960
+ spatial: {
7961
+ additionalProperties: false,
7962
+ properties: {
7963
+ chr: {
7964
+ type: "string"
7965
+ },
7966
+ coord: {
7967
+ type: "string"
7968
+ },
7969
+ x: {
7970
+ type: "string"
7971
+ },
7972
+ y: {
7973
+ type: "string"
7974
+ },
7975
+ z: {
7976
+ type: "string"
7977
+ }
7978
+ },
7979
+ required: [
7980
+ "x",
7981
+ "y",
7982
+ "z",
7983
+ "chr",
7984
+ "coord"
7985
+ ],
7986
+ type: "object"
7987
+ },
7321
7988
  startAngle: {
7322
7989
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
7323
7990
  type: "number"
@@ -7568,6 +8235,34 @@ const definitions$1 = {
7568
8235
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
7569
8236
  type: "number"
7570
8237
  },
8238
+ spatial: {
8239
+ additionalProperties: false,
8240
+ properties: {
8241
+ chr: {
8242
+ type: "string"
8243
+ },
8244
+ coord: {
8245
+ type: "string"
8246
+ },
8247
+ x: {
8248
+ type: "string"
8249
+ },
8250
+ y: {
8251
+ type: "string"
8252
+ },
8253
+ z: {
8254
+ type: "string"
8255
+ }
8256
+ },
8257
+ required: [
8258
+ "x",
8259
+ "y",
8260
+ "z",
8261
+ "chr",
8262
+ "coord"
8263
+ ],
8264
+ type: "object"
8265
+ },
7571
8266
  startAngle: {
7572
8267
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
7573
8268
  type: "number"
@@ -7927,6 +8622,16 @@ const definitions$1 = {
7927
8622
  description: "Specify an ID for [linking multiple views](http://gosling-lang.org/docs/user-interaction#linking-views)",
7928
8623
  type: "string"
7929
8624
  },
8625
+ locus: {
8626
+ anyOf: [
8627
+ {
8628
+ $ref: "#/definitions/X"
8629
+ },
8630
+ {
8631
+ $ref: "#/definitions/ChannelValue"
8632
+ }
8633
+ ]
8634
+ },
7930
8635
  mark: {
7931
8636
  $ref: "#/definitions/Mark"
7932
8637
  },
@@ -7985,6 +8690,34 @@ const definitions$1 = {
7985
8690
  description: "The size of the gap (1) between tracks, (2) between views, and (3) of the origin of circular tracks. The effect of this property depends on where on the spec you specify the `spacing`.\n\nIn a linear layout, this value is used in pixels, while in a circular layout, this value is used relative to the height of the tracks or views.",
7986
8691
  type: "number"
7987
8692
  },
8693
+ spatial: {
8694
+ additionalProperties: false,
8695
+ properties: {
8696
+ chr: {
8697
+ type: "string"
8698
+ },
8699
+ coord: {
8700
+ type: "string"
8701
+ },
8702
+ x: {
8703
+ type: "string"
8704
+ },
8705
+ y: {
8706
+ type: "string"
8707
+ },
8708
+ z: {
8709
+ type: "string"
8710
+ }
8711
+ },
8712
+ required: [
8713
+ "x",
8714
+ "y",
8715
+ "z",
8716
+ "chr",
8717
+ "coord"
8718
+ ],
8719
+ type: "object"
8720
+ },
7988
8721
  startAngle: {
7989
8722
  description: 'Specify the start angle (in the range of [0, 360]) of circular tracks (`{"layout": "circular"}`).',
7990
8723
  type: "number"
@@ -12369,9 +13102,9 @@ class PixiTrack extends Track {
12369
13102
  if (this.options && this.options.dataTransform) {
12370
13103
  let chosenTransform = null;
12371
13104
  if (this.tilesetInfo && this.tilesetInfo.transforms) {
12372
- for (const transform of this.tilesetInfo.transforms) {
12373
- if (transform.value === this.options.dataTransform) {
12374
- chosenTransform = transform;
13105
+ for (const transform2 of this.tilesetInfo.transforms) {
13106
+ if (transform2.value === this.options.dataTransform) {
13107
+ chosenTransform = transform2;
12375
13108
  }
12376
13109
  }
12377
13110
  }
@@ -18270,6 +19003,7 @@ var TrackType = /* @__PURE__ */ ((TrackType2) => {
18270
19003
  TrackType2[TrackType2["BrushLinear"] = 4] = "BrushLinear";
18271
19004
  TrackType2[TrackType2["BrushCircular"] = 5] = "BrushCircular";
18272
19005
  TrackType2[TrackType2["Heatmap"] = 6] = "Heatmap";
19006
+ TrackType2[TrackType2["Spatial"] = 7] = "Spatial";
18273
19007
  return TrackType2;
18274
19008
  })(TrackType || {});
18275
19009
  function createTrackDefs(trackInfos, theme) {
@@ -18285,6 +19019,18 @@ function createTrackDefs(trackInfos, theme) {
18285
19019
  } else if (IsDummyTrack(track)) {
18286
19020
  const dummyTrackDefs = processDummyTrack(track, boundingBox, theme);
18287
19021
  trackDefs.push(...dummyTrackDefs);
19022
+ } else if ("layout" in track && track.layout === "spatial") {
19023
+ const trackDef = {
19024
+ type: 7,
19025
+ trackId: track.id,
19026
+ boundingBox,
19027
+ options: {
19028
+ // @ts-expect-error At this point, the spec is processed
19029
+ spec: track,
19030
+ processedSpec: track
19031
+ }
19032
+ };
19033
+ trackDefs.push(trackDef);
18288
19034
  } else {
18289
19035
  const goslingAxisDefs = processGoslingTrack(track, boundingBox, theme);
18290
19036
  trackDefs.push(...goslingAxisDefs);
@@ -26021,6 +26767,53 @@ class BigWigDataFetcher {
26021
26767
  return level || reductionLevels.slice(-1)[0];
26022
26768
  }
26023
26769
  }
26770
+ /**
26771
+ * Make an assertion.
26772
+ *
26773
+ * Usage
26774
+ * @example
26775
+ * ```ts
26776
+ * const value: boolean = Math.random() <= 0.5;
26777
+ * assert(value, "value is greater than than 0.5!");
26778
+ * value // true
26779
+ * ```
26780
+ *
26781
+ * @copyright Trevor Manz 2025
26782
+ * @license MIT
26783
+ * @see {@link https://github.com/manzt/manzt/blob/f7faee/utils/assert.js}
26784
+ */
26785
+ function assert(expression, msg = "") {
26786
+ if (!expression)
26787
+ throw new Error(msg);
26788
+ }
26789
+ async function transform(t, data, xScale, assembly) {
26790
+ switch (t.type) {
26791
+ case "filter":
26792
+ return filterData(t, data);
26793
+ case "join":
26794
+ return await joinData(t, data, assembly);
26795
+ case "concat":
26796
+ return concatString(t, data);
26797
+ case "replace":
26798
+ return replaceString(t, data);
26799
+ case "log":
26800
+ return calculateData(t, data);
26801
+ case "exonSplit":
26802
+ return splitExon(t, data, assembly);
26803
+ case "genomicLength":
26804
+ return calculateGenomicLength(t, data);
26805
+ case "svType":
26806
+ return inferSvType(t, data);
26807
+ case "coverage":
26808
+ assert(xScale, "xScale parameters is required for coverage transform");
26809
+ return aggregateCoverage(t, data, xScale);
26810
+ case "subjson":
26811
+ return parseSubJSON(t, data);
26812
+ case "displace":
26813
+ assert(xScale, "xScale parameters is required for displace transform");
26814
+ return displace(t, data, xScale);
26815
+ }
26816
+ }
26024
26817
  function filterData(filter, data) {
26025
26818
  const { field, not } = filter;
26026
26819
  let output = Array.from(data);
@@ -26043,6 +26836,41 @@ function filterData(filter, data) {
26043
26836
  }
26044
26837
  return output;
26045
26838
  }
26839
+ const FETCH_CACHE = {};
26840
+ async function joinData(transform2, toData, assembly = "hg19") {
26841
+ const { from, to } = transform2;
26842
+ const fetchDataIfNeeded = async (url) => {
26843
+ var _a, _b;
26844
+ if (FETCH_CACHE[url])
26845
+ return FETCH_CACHE[url];
26846
+ const response = await fetch(url);
26847
+ const text2 = await response.text();
26848
+ const data = dsvFormat(",").parse(text2);
26849
+ const chromSizes = computeChromSizes(assembly);
26850
+ for (const d of data) {
26851
+ const chrName = d[from.chromosomeField];
26852
+ const chromPosition = d[from.genomicField];
26853
+ d[from.genomicField] = ((_b = (_a = chromSizes.interval[chrName]) == null ? void 0 : _a[0]) != null ? _b : 0) + +chromPosition;
26854
+ }
26855
+ FETCH_CACHE[url] = data;
26856
+ return data;
26857
+ };
26858
+ const fromData = await fetchDataIfNeeded(from.url);
26859
+ const joinned = fromData.map((f) => {
26860
+ var _a;
26861
+ const found = (_a = toData.find((t) => {
26862
+ if (to.endField) {
26863
+ const start = +t[to.startField] <= +f[from.genomicField];
26864
+ const end = +t[to.endField] >= +f[from.genomicField];
26865
+ return start && end;
26866
+ } else {
26867
+ return +t[to.startField] == +f[from.genomicField];
26868
+ }
26869
+ })) != null ? _a : { value: 0 };
26870
+ return { ...f, ...found };
26871
+ });
26872
+ return joinned;
26873
+ }
26046
26874
  function concatString(concat, data) {
26047
26875
  const { fields, separator, newField } = concat;
26048
26876
  let output = Array.from(data);
@@ -26969,7 +27797,7 @@ class LinearBrushModel {
26969
27797
  }
26970
27798
  const GOSLING_DATA_ROW_UID_FIELD = "gosling-data-row-uid";
26971
27799
  function getTabularData(spec, data) {
26972
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
27800
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
26973
27801
  const tabularData = [];
26974
27802
  if (!IsDataDeepTileset(spec.data)) {
26975
27803
  console.warn("No data is specified");
@@ -26981,28 +27809,29 @@ function getTabularData(spec, data) {
26981
27809
  }
26982
27810
  const bin = (_a = spec.data.binSize) != null ? _a : 1;
26983
27811
  const numericValues = data.dense;
26984
- const numOfGenomicPositions = data.tileSize;
26985
- const tileUnitSize = data.tileWidth / data.tileSize;
26986
- const valueName = (_b = spec.data.value) != null ? _b : "value";
26987
- const columnName = (_c = spec.data.column) != null ? _c : "position";
26988
- const startName = (_d = spec.data.start) != null ? _d : "start";
26989
- const endName = (_e = spec.data.end) != null ? _e : "end";
27812
+ const numOfGenomicPositions = (_b = data.tileSize) != null ? _b : data.dense.length;
27813
+ const tileUnitSize = ((_c = data.tileWidth) != null ? _c : 1024) / numOfGenomicPositions;
27814
+ const valueName = (_d = spec.data.value) != null ? _d : "value";
27815
+ const columnName = (_e = spec.data.column) != null ? _e : "position";
27816
+ const startName = (_f = spec.data.start) != null ? _f : "start";
27817
+ const endName = (_g = spec.data.end) != null ? _g : "end";
26990
27818
  const minValueName = `${valueName}_min`;
26991
27819
  const maxValueName = `${valueName}_max`;
26992
- const agg = (_f = spec.data.aggregation) != null ? _f : "mean";
27820
+ const agg = (_h = spec.data.aggregation) != null ? _h : "mean";
26993
27821
  let cumVal = 0;
26994
27822
  let minVal = Number.MAX_SAFE_INTEGER;
26995
27823
  let maxVal = Number.MIN_SAFE_INTEGER;
26996
27824
  let binStart = Number.MIN_SAFE_INTEGER;
26997
27825
  let binEnd = Number.MAX_SAFE_INTEGER;
26998
27826
  Array.from(Array(numOfGenomicPositions).keys()).forEach((g, j) => {
27827
+ var _a2, _b2, _c2;
26999
27828
  if (bin === 1) {
27000
27829
  const value = numericValues[j] / (agg === "mean" ? tileUnitSize : 1);
27001
27830
  tabularData.push({
27002
27831
  [valueName]: value,
27003
- [columnName]: data.tileX + (j + 0.5) * tileUnitSize,
27004
- [startName]: data.tileX + j * tileUnitSize,
27005
- [endName]: data.tileX + (j + 1) * tileUnitSize,
27832
+ [columnName]: ((_a2 = data.tileX) != null ? _a2 : 0) + (j + 0.5) * tileUnitSize,
27833
+ [startName]: ((_b2 = data.tileX) != null ? _b2 : 0) + j * tileUnitSize,
27834
+ [endName]: ((_c2 = data.tileX) != null ? _c2 : 0) + (j + 1) * tileUnitSize,
27006
27835
  [minValueName]: value,
27007
27836
  [maxValueName]: value
27008
27837
  });
@@ -27044,20 +27873,20 @@ function getTabularData(spec, data) {
27044
27873
  if (!("dense" in data) || data.shape === void 0) {
27045
27874
  return;
27046
27875
  }
27047
- const bin = (_g = spec.data.binSize) != null ? _g : 1;
27876
+ const bin = (_i = spec.data.binSize) != null ? _i : 1;
27048
27877
  const numOfTotalCategories = data.shape[0];
27049
- const categories = (_h = spec.data.categories) != null ? _h : [...Array(numOfTotalCategories).keys()];
27878
+ const categories = (_j = spec.data.categories) != null ? _j : [...Array(numOfTotalCategories).keys()];
27050
27879
  const numericValues = data.dense;
27051
27880
  const numOfGenomicPositions = data.shape[1];
27052
27881
  const tileUnitSize = data.tileWidth / data.tileSize;
27053
- const rowName = (_i = spec.data.row) != null ? _i : "category";
27054
- const valueName = (_j = spec.data.value) != null ? _j : "value";
27055
- const columnName = (_k = spec.data.column) != null ? _k : "position";
27056
- const startName = (_l = spec.data.start) != null ? _l : "start";
27057
- const endName = (_m = spec.data.end) != null ? _m : "end";
27882
+ const rowName = (_k = spec.data.row) != null ? _k : "category";
27883
+ const valueName = (_l = spec.data.value) != null ? _l : "value";
27884
+ const columnName = (_m = spec.data.column) != null ? _m : "position";
27885
+ const startName = (_n = spec.data.start) != null ? _n : "start";
27886
+ const endName = (_o = spec.data.end) != null ? _o : "end";
27058
27887
  const minValueName = `${valueName}_min`;
27059
27888
  const maxValueName = `${valueName}_max`;
27060
- const agg = (_n = spec.data.aggregation) != null ? _n : "mean";
27889
+ const agg = (_p = spec.data.aggregation) != null ? _p : "mean";
27061
27890
  categories.forEach((c, i) => {
27062
27891
  let cumVal = 0;
27063
27892
  let binStart = Number.MIN_SAFE_INTEGER;
@@ -27123,8 +27952,8 @@ function getTabularData(spec, data) {
27123
27952
  const numericValues = data.dense;
27124
27953
  const tileXUnitSize = tileWidth / numBins;
27125
27954
  const tileYUnitSize = tileHeight / numBins;
27126
- const columnField = (_o = spec.data.column) != null ? _o : "x";
27127
- const rowField = (_p = spec.data.row) != null ? _p : "y";
27955
+ const columnField = (_q = spec.data.column) != null ? _q : "x";
27956
+ const rowField = (_r = spec.data.row) != null ? _r : "y";
27128
27957
  const aggSize = 16;
27129
27958
  for (let i = 0; i < numericValues.length / aggSize; i++) {
27130
27959
  const aggLen = Math.sqrt(aggSize);
@@ -28593,14 +29422,18 @@ const _GoslingTrackClass = class _GoslingTrackClass extends TiledPixiTrack {
28593
29422
  }
28594
29423
  tiles.forEach((tile) => __privateMethod(this, _generateTabularData, generateTabularData_fn).call(this, tile, force));
28595
29424
  this.combineAllTilesIfNeeded();
28596
- const models = tiles.flatMap((tile) => this.transformDataAndCreateModels(tile));
28597
- shareScaleAcrossTracks(models);
28598
- const flatTileData = [].concat(...models.map((d) => d.data()));
28599
- if (flatTileData.length !== 0) {
28600
- publish("rawData", { id: this.options.id, data: flatTileData });
28601
- }
28602
- tiles.forEach((tile) => {
28603
- __privateGet(this, _processedTileMap).set(tile, true);
29425
+ Promise.all(tiles.flatMap((tile) => this.transformDataAndCreateModels(tile))).then((n) => {
29426
+ const models = n.flat();
29427
+ shareScaleAcrossTracks(models);
29428
+ const flatTileData = [].concat(...models.map((d) => d.data()));
29429
+ if (flatTileData.length !== 0) {
29430
+ publish("rawData", { id: this.options.id, data: flatTileData });
29431
+ }
29432
+ tiles.forEach((tile) => {
29433
+ __privateGet(this, _processedTileMap).set(tile, true);
29434
+ });
29435
+ this.draw();
29436
+ this.forceDraw();
28604
29437
  });
28605
29438
  }
28606
29439
  /**
@@ -28858,50 +29691,24 @@ const _GoslingTrackClass = class _GoslingTrackClass extends TiledPixiTrack {
28858
29691
  /**
28859
29692
  * Apply data transformation to each of the overlaid tracks and generate GoslingTrackModels.
28860
29693
  */
28861
- transformDataAndCreateModels(tile) {
29694
+ async transformDataAndCreateModels(tile) {
29695
+ var _a;
28862
29696
  const tileInfo = __privateGet(this, _processedTileInfo)[tile.tileId];
28863
29697
  if (!tileInfo || tileInfo.skipRendering) {
28864
29698
  return [];
28865
29699
  }
28866
29700
  tileInfo.goslingModels = [];
28867
29701
  const resolvedTracks = this.getResolvedTracks();
28868
- resolvedTracks.forEach((resolvedSpec) => {
28869
- var _a;
29702
+ for (const resolvedSpec of resolvedTracks) {
28870
29703
  let tabularDataTransformed = Array.from(tileInfo.tabularData);
28871
- (_a = resolvedSpec.dataTransform) == null ? void 0 : _a.forEach((t) => {
28872
- switch (t.type) {
28873
- case "filter":
28874
- tabularDataTransformed = filterData(t, tabularDataTransformed);
28875
- break;
28876
- case "concat":
28877
- tabularDataTransformed = concatString(t, tabularDataTransformed);
28878
- break;
28879
- case "replace":
28880
- tabularDataTransformed = replaceString(t, tabularDataTransformed);
28881
- break;
28882
- case "log":
28883
- tabularDataTransformed = calculateData(t, tabularDataTransformed);
28884
- break;
28885
- case "exonSplit":
28886
- tabularDataTransformed = splitExon(t, tabularDataTransformed, resolvedSpec.assembly);
28887
- break;
28888
- case "genomicLength":
28889
- tabularDataTransformed = calculateGenomicLength(t, tabularDataTransformed);
28890
- break;
28891
- case "svType":
28892
- tabularDataTransformed = inferSvType(t, tabularDataTransformed);
28893
- break;
28894
- case "coverage":
28895
- tabularDataTransformed = aggregateCoverage(t, tabularDataTransformed, this._xScale.copy());
28896
- break;
28897
- case "subjson":
28898
- tabularDataTransformed = parseSubJSON(t, tabularDataTransformed);
28899
- break;
28900
- case "displace":
28901
- tabularDataTransformed = displace(t, tabularDataTransformed, this._xScale.copy());
28902
- break;
28903
- }
28904
- });
29704
+ for (const t of (_a = resolvedSpec.dataTransform) != null ? _a : []) {
29705
+ tabularDataTransformed = await transform(
29706
+ t,
29707
+ tabularDataTransformed,
29708
+ this.xScale().copy(),
29709
+ resolvedSpec.assembly
29710
+ );
29711
+ }
28905
29712
  try {
28906
29713
  if (PubSub) {
28907
29714
  const NUM_OF_ROWS_IN_PREVIEW = 100;
@@ -28929,7 +29736,7 @@ const _GoslingTrackClass = class _GoslingTrackClass extends TiledPixiTrack {
28929
29736
  resolvedSpec.height = h;
28930
29737
  const model = new GoslingTrackModel(resolvedSpec, tabularDataTransformed, this.options.theme);
28931
29738
  tileInfo.goslingModels.push(model);
28932
- });
29739
+ }
28933
29740
  return tileInfo.goslingModels;
28934
29741
  }
28935
29742
  /* *
@@ -29634,9 +30441,9 @@ function panZoomHeatmap(plot, xDomain, yDomain) {
29634
30441
  const baseXScale = scaleLinear().range([0, width]);
29635
30442
  const baseYScale = scaleLinear().range([0, height]);
29636
30443
  const zoomed = (event) => {
29637
- const { transform } = event;
29638
- const newXDomain = transform.rescaleX(zoomStartXScale).domain();
29639
- const newYDomain = transform.rescaleY(zoomStartYScale).domain();
30444
+ const { transform: transform2 } = event;
30445
+ const newXDomain = transform2.rescaleX(zoomStartXScale).domain();
30446
+ const newYDomain = transform2.rescaleY(zoomStartYScale).domain();
29640
30447
  batch(() => {
29641
30448
  xDomain.value = newXDomain;
29642
30449
  yDomain.value = newYDomain;
@@ -29737,9 +30544,9 @@ function panZoomCircular(plot, cursorPos, xDomain) {
29737
30544
  let zoomStartPos = 0;
29738
30545
  let panStartDomain = [0, 0];
29739
30546
  const zoomed = (event) => {
29740
- const { transform, sourceEvent } = event;
30547
+ const { transform: transform2, sourceEvent } = event;
29741
30548
  if (sourceEvent && sourceEvent.type === "wheel") {
29742
- const newXDomain = transform.rescaleX(zoomStartScaleX).domain();
30549
+ const newXDomain = transform2.rescaleX(zoomStartScaleX).domain();
29743
30550
  const newDomain = newXDomain[1] - newXDomain[0];
29744
30551
  const originalDomain = zoomStartScaleX.domain()[1] - zoomStartScaleX.domain()[0];
29745
30552
  const mouseRelativePos = (zoomStartPos - zoomStartScaleX.domain()[0]) / originalDomain;
@@ -29783,10 +30590,11 @@ function panZoomCircular(plot, cursorPos, xDomain) {
29783
30590
  select(plot.domOverlay).call(zoomBehavior);
29784
30591
  }
29785
30592
  function getDataFetcher(spec, urlToFetchOptions) {
30593
+ var _a;
29786
30594
  const { data, assembly = "hg38" } = spec;
29787
30595
  if (typeof data === "undefined") {
29788
30596
  console.warn("No data in the track spec", spec);
29789
- return;
30597
+ return new JsonDataFetcherClass({ type: "json", values: [], assembly: (_a = spec.assembly) != null ? _a : "unknown" });
29790
30598
  }
29791
30599
  const { type } = data;
29792
30600
  const urlFetchOptions = "url" in data && (urlToFetchOptions == null ? void 0 : urlToFetchOptions[data.url]) || {};
@@ -29837,6 +30645,265 @@ function getFields(spec) {
29837
30645
  }
29838
30646
  return fields;
29839
30647
  }
30648
+ const ERROR_COLOR = "#ff00ff";
30649
+ async function transformObjectToArrow(t, options) {
30650
+ var _a, _b, _c;
30651
+ let tabularData = (_a = t["0.0"].tabularData) != null ? _a : getTabularData(options.spec, t["0.0"]);
30652
+ tabularData = structuredClone(tabularData);
30653
+ for (const t2 of (_b = options.spec.dataTransform) != null ? _b : []) {
30654
+ tabularData = await transform(t2, tabularData, void 0, options.spec.assembly);
30655
+ }
30656
+ const xArr = [];
30657
+ const yArr = [];
30658
+ const zArr = [];
30659
+ const chrArr = [];
30660
+ const coordArr = [];
30661
+ const parseAsNumber = (e) => {
30662
+ if (typeof e === "string") {
30663
+ return parseFloat(e);
30664
+ }
30665
+ return e;
30666
+ };
30667
+ assert(options.processedSpec.spatial, "ProcessedSpatilTrack is missing the definition for spatial coordinates.");
30668
+ const spatialMapping = options.processedSpec.spatial;
30669
+ const fieldForSpatialX = spatialMapping.x;
30670
+ const fieldForSpatialY = spatialMapping.y;
30671
+ const fieldForSpatialZ = spatialMapping.z;
30672
+ const fieldForSpatialChr = spatialMapping.chr;
30673
+ const fieldForSpatialCoord = spatialMapping.coord;
30674
+ for (const [i] of tabularData.entries()) {
30675
+ xArr.push(parseAsNumber(tabularData[i][fieldForSpatialX]));
30676
+ yArr.push(parseAsNumber(tabularData[i][fieldForSpatialY]));
30677
+ zArr.push(parseAsNumber(tabularData[i][fieldForSpatialZ]));
30678
+ chrArr.push(tabularData[i][fieldForSpatialChr]);
30679
+ coordArr.push(parseAsNumber(tabularData[i][fieldForSpatialCoord]));
30680
+ }
30681
+ let arrays = {
30682
+ x: xArr,
30683
+ y: yArr,
30684
+ z: zArr,
30685
+ chr: chrArr,
30686
+ coord: coordArr
30687
+ };
30688
+ const allFields = Object.keys((_c = tabularData[0]) != null ? _c : {});
30689
+ const alreadyAddedFields = [
30690
+ fieldForSpatialX,
30691
+ fieldForSpatialY,
30692
+ fieldForSpatialZ,
30693
+ fieldForSpatialChr,
30694
+ fieldForSpatialCoord
30695
+ ];
30696
+ const additionalFields = [];
30697
+ for (const c of allFields) {
30698
+ if (alreadyAddedFields.indexOf(c) === -1) {
30699
+ additionalFields.push(c);
30700
+ }
30701
+ }
30702
+ const suppArray = {};
30703
+ for (const d of tabularData) {
30704
+ for (const f of additionalFields) {
30705
+ if (!suppArray[f]) {
30706
+ suppArray[f] = [];
30707
+ }
30708
+ suppArray[f].push(Number.isNaN(+d[f]) ? d[f] : parseAsNumber(d[f]));
30709
+ }
30710
+ }
30711
+ arrays = { ...suppArray, ...arrays };
30712
+ const table = tableFromArrays(arrays);
30713
+ const buffer = tableToIPC(table, { format: "file" });
30714
+ return buffer;
30715
+ }
30716
+ function fetchValuesFromColumn(columnName, arrowIpc) {
30717
+ const table = tableFromIPC(arrowIpc);
30718
+ const column = table.getChild(columnName);
30719
+ const t = column.type;
30720
+ if (t.typeId === Type.Int || t.typeId === Type.Float) {
30721
+ return column.toArray();
30722
+ } else if (t.typeId === Type.Dictionary || t.typeId === Type.Utf8) {
30723
+ return column.toArray();
30724
+ }
30725
+ return void 0;
30726
+ }
30727
+ function findMinAndMaxOfColumn(column) {
30728
+ let minVal = Infinity;
30729
+ let maxVal = -Infinity;
30730
+ for (const v of column) {
30731
+ minVal = Math.min(minVal, v);
30732
+ maxVal = Math.max(maxVal, v);
30733
+ }
30734
+ return [minVal, maxVal];
30735
+ }
30736
+ function getRange(size) {
30737
+ if (size.range) {
30738
+ return [size.range[0], size.range[1]];
30739
+ } else {
30740
+ return [0.01, 1e-3];
30741
+ }
30742
+ }
30743
+ const randomColors = (n) => {
30744
+ const colors = [];
30745
+ for (let j = 0; j < n; j++) {
30746
+ let colorStr = "#";
30747
+ for (let i = 0; i < 6; i++) {
30748
+ const maxNum = 16;
30749
+ const randNum = Math.floor(Math.random() * maxNum);
30750
+ colorStr += randNum.toString(16);
30751
+ }
30752
+ colors.push(colorStr);
30753
+ }
30754
+ return colors;
30755
+ };
30756
+ function handleColorField(arrowIpc, color2) {
30757
+ var _a, _b;
30758
+ if (color2 === void 0) {
30759
+ return "red";
30760
+ } else if (typeof color2 === "string") {
30761
+ return color2;
30762
+ } else if ("value" in color2) {
30763
+ return color2.value;
30764
+ } else if ("field" in color2) {
30765
+ if (!color2.type) {
30766
+ color2.type = "nominal";
30767
+ }
30768
+ if (color2.type === "nominal") {
30769
+ assert(color2.field, "color.field is required for nominal color");
30770
+ const values = fetchValuesFromColumn(color2.field, arrowIpc);
30771
+ const colScale = (_a = color2.range) != null ? _a : randomColors(50);
30772
+ assert(
30773
+ typeof colScale === "string" || Array.isArray(colScale) && colScale.every((it) => typeof it === "string"),
30774
+ "color.range must be a string or an array of strings"
30775
+ );
30776
+ const colorConfig = {
30777
+ values: [...values],
30778
+ min: 0,
30779
+ max: values.length - 1,
30780
+ colorScale: colScale
30781
+ };
30782
+ return colorConfig;
30783
+ } else if (color2.type === "quantitative") {
30784
+ assert(color2.field, "color.field is required for quantitative color");
30785
+ const values = fetchValuesFromColumn(color2.field, arrowIpc);
30786
+ assert(values, "color.field must be a valid field in the data table");
30787
+ assert(
30788
+ values.every((it) => typeof it === "number"),
30789
+ "color.field must be a numeric field"
30790
+ );
30791
+ const [minVal, maxVal] = color2.domain ? [color2.domain[0], color2.domain[1]] : findMinAndMaxOfColumn(values);
30792
+ const colScale = (_b = color2.range) != null ? _b : "viridis";
30793
+ assert(
30794
+ typeof colScale === "string" || Array.isArray(colScale) && colScale.every((it) => typeof it === "string"),
30795
+ "color.range must be a string or an array of strings"
30796
+ );
30797
+ const colorConfig = {
30798
+ values: [...values],
30799
+ min: Number(minVal),
30800
+ max: Number(maxVal),
30801
+ colorScale: colScale
30802
+ };
30803
+ return colorConfig;
30804
+ } else {
30805
+ return ERROR_COLOR;
30806
+ }
30807
+ } else {
30808
+ return ERROR_COLOR;
30809
+ }
30810
+ }
30811
+ function handleSizeField(arrowIpc, size) {
30812
+ if (size === void 0) {
30813
+ return 0.01;
30814
+ } else if (typeof size === "number") {
30815
+ return size;
30816
+ } else if ("value" in size) {
30817
+ return size.value;
30818
+ } else if ("field" in size) {
30819
+ if (!size.type) {
30820
+ size.type = "quantitative";
30821
+ }
30822
+ if (size.type === "nominal") {
30823
+ console.warn("not implemented!");
30824
+ } else if (size.type === "quantitative") {
30825
+ assert(size.field, "size.field is required for quantitative size");
30826
+ const values = fetchValuesFromColumn(size.field, arrowIpc);
30827
+ const [rangeMax, rangeMin] = getRange(size);
30828
+ assert(values, "size.field must be a valid field in the data table");
30829
+ assert(
30830
+ values.every((it) => typeof it === "number"),
30831
+ "size.field must be a numeric field"
30832
+ );
30833
+ const [minVal, maxVal] = findMinAndMaxOfColumn(values);
30834
+ const sizeConfig = {
30835
+ values: [...values],
30836
+ min: minVal,
30837
+ max: maxVal,
30838
+ scaleMin: rangeMin,
30839
+ scaleMax: rangeMax
30840
+ };
30841
+ return sizeConfig;
30842
+ } else {
30843
+ return 0.01;
30844
+ }
30845
+ }
30846
+ return 0.01;
30847
+ }
30848
+ function createSpatialTrack(options, dataFetcher, container) {
30849
+ dataFetcher.tilesetInfo((info) => {
30850
+ dataFetcher.fetchTilesDebounced(
30851
+ async (t) => {
30852
+ var _a;
30853
+ if (!t["0.0"].tileWidth) {
30854
+ t["0.0"].tileWidth = info.max_width;
30855
+ }
30856
+ const ipcBuffer = await transformObjectToArrow(t, options);
30857
+ if (!ipcBuffer) {
30858
+ console.error("could not tranform into Apache Arrow");
30859
+ return;
30860
+ }
30861
+ let chromatinScene = uchi.initScene();
30862
+ let tracks = [];
30863
+ if ("_overlay" in options.spec) {
30864
+ tracks = options.spec._overlay;
30865
+ } else {
30866
+ tracks = [options.spec];
30867
+ }
30868
+ for (const ov of tracks) {
30869
+ const color2 = handleColorField(ipcBuffer, ov.color);
30870
+ const scale = handleSizeField(ipcBuffer, ov.size);
30871
+ if (!ov.mark) {
30872
+ ov.mark = "sphere";
30873
+ }
30874
+ assert(
30875
+ ov.mark === "sphere" || ov.mark === "octahedron" || ov.mark === "box",
30876
+ "Unsupported mark type for spatial view"
30877
+ );
30878
+ const viewConfig = {
30879
+ scale,
30880
+ color: color2,
30881
+ mark: ov.mark
30882
+ };
30883
+ let s = uchi.load(ipcBuffer.slice().buffer, { center: true, normalize: true });
30884
+ const filterTransform = ((_a = ov.dataTransform) != null ? _a : []).find((t2) => t2.type === "filter");
30885
+ if (filterTransform) {
30886
+ const field = filterTransform.field;
30887
+ assert(field === "chr", "Field for transform should be 'chr'");
30888
+ assert("oneOf" in filterTransform, "oneOf is required for this filter transform");
30889
+ const oneOf = filterTransform.oneOf;
30890
+ const first = oneOf[0];
30891
+ assert(typeof first === "string", "only string is supported for chromosome filtering");
30892
+ const res = await uchi.selectChromosome(s.data, first);
30893
+ console.warn(`selectChromosome result: res.numRows = ${res.numRows}`);
30894
+ if (res) {
30895
+ s = { data: res, name: `Filtered structure (${oneOf})` };
30896
+ }
30897
+ }
30898
+ chromatinScene = uchi.addStructureToScene(chromatinScene, s, viewConfig);
30899
+ }
30900
+ const [, createdCanvas] = uchi.display(chromatinScene, { alwaysRedraw: false, withHUD: false });
30901
+ container.appendChild(createdCanvas);
30902
+ },
30903
+ ["0.0"]
30904
+ );
30905
+ });
30906
+ }
29840
30907
  function renderTrackDefs(trackDefs, linkedEncodings, pixiManager, urlToFetchOptions) {
29841
30908
  const plotDict = {};
29842
30909
  const cursorPosX = signal(Number.NEGATIVE_INFINITY);
@@ -29952,6 +31019,18 @@ function renderTrackDefs(trackDefs, linkedEncodings, pixiManager, urlToFetchOpti
29952
31019
  const dummyPlot = new DummyTrack(dummyOptions, pixiManager.makeContainer(boundingBox).overlayDiv);
29953
31020
  plotDict[trackId] = dummyPlot;
29954
31021
  }
31022
+ if (type === TrackType.Spatial) {
31023
+ const container = pixiManager.makeContainer(boundingBox).overlayDiv;
31024
+ const spatialTrackOptions = options;
31025
+ console.warn("!@$!#%@# detected spatial track !@#$!#%@#");
31026
+ if (spatialTrackOptions.spec.data) {
31027
+ if ("sampleLength" in spatialTrackOptions.spec.data) {
31028
+ spatialTrackOptions.spec.data.sampleLength = 3e4;
31029
+ }
31030
+ }
31031
+ const datafetcher = getDataFetcher(spatialTrackOptions.spec, urlToFetchOptions);
31032
+ createSpatialTrack(spatialTrackOptions, datafetcher, container);
31033
+ }
29955
31034
  });
29956
31035
  return plotDict;
29957
31036
  }