@genome-spy/core 0.18.1 → 0.20.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 (91) hide show
  1. package/dist/index.js +46 -119
  2. package/dist/schema.json +213 -22
  3. package/package.json +4 -3
  4. package/src/data/collector.js +9 -4
  5. package/src/data/collector.test.js +2 -0
  6. package/src/data/dataFlow.test.js +2 -0
  7. package/src/data/flow.test.js +1 -0
  8. package/src/data/flowNode.test.js +1 -0
  9. package/src/data/flowOptimizer.js +6 -0
  10. package/src/data/flowOptimizer.test.js +1 -0
  11. package/src/data/formats/fasta.test.js +1 -0
  12. package/src/data/sources/inlineSource.test.js +1 -0
  13. package/src/data/sources/sequenceSource.test.js +1 -0
  14. package/src/data/transforms/clone.test.js +1 -0
  15. package/src/data/transforms/coverage.test.js +1 -0
  16. package/src/data/transforms/filter.test.js +1 -0
  17. package/src/data/transforms/flattenDelimited.test.js +1 -0
  18. package/src/data/transforms/flattenSequence.test.js +1 -0
  19. package/src/data/transforms/formula.test.js +1 -0
  20. package/src/data/transforms/identifier.test.js +1 -0
  21. package/src/data/transforms/pileup.test.js +1 -0
  22. package/src/data/transforms/project.test.js +1 -0
  23. package/src/data/transforms/regexExtract.test.js +1 -0
  24. package/src/data/transforms/regexFold.test.js +1 -0
  25. package/src/data/transforms/sample.test.js +1 -0
  26. package/src/data/transforms/stack.test.js +1 -0
  27. package/src/encoder/accessor.test.js +1 -0
  28. package/src/encoder/encoder.test.js +1 -0
  29. package/src/genome/genome.js +14 -2
  30. package/src/genome/genome.test.js +36 -0
  31. package/src/genome/scaleIndex.js +3 -2
  32. package/src/genome/scaleIndex.test.js +23 -6
  33. package/src/genome/scaleLocus.test.js +1 -0
  34. package/src/genomeSpy.js +16 -11
  35. package/src/gl/dataToVertices.js +9 -6
  36. package/src/gl/includes/common.glsl +3 -3
  37. package/src/gl/includes/scales.glsl +33 -2
  38. package/src/gl/point.vertex.glsl +0 -2
  39. package/src/gl/rule.vertex.glsl +1 -1
  40. package/src/gl/webGLHelper.js +0 -3
  41. package/src/marks/mark.js +15 -14
  42. package/src/scale/glslScaleGenerator.js +56 -17
  43. package/src/scale/scale.test.js +1 -0
  44. package/src/scale/ticks.test.js +1 -0
  45. package/src/spec/scale.d.ts +0 -9
  46. package/src/spec/title.d.ts +102 -0
  47. package/src/spec/view.d.ts +6 -4
  48. package/src/tooltip/dataTooltipHandler.js +3 -2
  49. package/src/utils/addBaseUrl.test.js +1 -0
  50. package/src/utils/cloner.test.js +1 -0
  51. package/src/utils/coalesce.test.js +1 -0
  52. package/src/utils/concatIterables.test.js +1 -0
  53. package/src/utils/domainArray.test.js +1 -0
  54. package/src/utils/indexer.test.js +1 -0
  55. package/src/utils/iterateNestedMaps.test.js +1 -0
  56. package/src/utils/kWayMerge.test.js +1 -0
  57. package/src/utils/layout/flexLayout.js +35 -3
  58. package/src/utils/layout/flexLayout.test.js +15 -0
  59. package/src/utils/layout/grid.js +95 -0
  60. package/src/utils/layout/grid.test.js +71 -0
  61. package/src/utils/layout/padding.js +13 -0
  62. package/src/utils/layout/rectangle.js +6 -0
  63. package/src/utils/layout/rectangle.test.js +1 -0
  64. package/src/utils/mergeObjects.test.js +1 -0
  65. package/src/utils/numberExtractor.test.js +1 -0
  66. package/src/utils/propertyCacher.test.js +1 -0
  67. package/src/utils/propertyCoalescer.test.js +1 -0
  68. package/src/utils/reservationMap.test.js +1 -0
  69. package/src/utils/topK.test.js +1 -0
  70. package/src/utils/variableTools.test.js +1 -0
  71. package/src/view/axisResolution.test.js +1 -0
  72. package/src/view/axisView.js +3 -1
  73. package/src/view/concatView.js +24 -275
  74. package/src/view/flowBuilder.test.js +1 -0
  75. package/src/view/gridView.js +774 -0
  76. package/src/view/implicitRootView.js +14 -0
  77. package/src/view/layerView.js +15 -1
  78. package/src/view/scaleResolution.js +5 -11
  79. package/src/view/scaleResolution.test.js +1 -0
  80. package/src/view/title.js +165 -0
  81. package/src/view/unitView.js +17 -9
  82. package/src/view/view.js +35 -14
  83. package/src/view/view.test.js +1 -0
  84. package/src/view/viewContext.d.ts +6 -1
  85. package/src/view/viewFactory.test.js +1 -0
  86. package/src/view/viewUtils.js +1 -93
  87. package/src/view/zoom.js +89 -0
  88. package/src/gl/includes/fp64-arithmetic.glsl +0 -187
  89. package/src/gl/includes/fp64-utils.js +0 -142
  90. package/src/gl/includes/scales_fp64.glsl +0 -30
  91. package/src/view/decoratorView.js +0 -513
package/dist/schema.json CHANGED
@@ -478,6 +478,9 @@
478
478
  "baseUrl": {
479
479
  "type": "string"
480
480
  },
481
+ "columns": {
482
+ "type": "number"
483
+ },
481
484
  "concat": {
482
485
  "items": {
483
486
  "anyOf": [
@@ -575,7 +578,14 @@
575
578
  "type": "number"
576
579
  },
577
580
  "title": {
578
- "type": "string"
581
+ "anyOf": [
582
+ {
583
+ "type": "string"
584
+ },
585
+ {
586
+ "$ref": "#/definitions/Title"
587
+ }
588
+ ]
579
589
  },
580
590
  "transform": {
581
591
  "items": {
@@ -606,7 +616,8 @@
606
616
  }
607
617
  },
608
618
  "required": [
609
- "concat"
619
+ "concat",
620
+ "columns"
610
621
  ],
611
622
  "type": "object"
612
623
  },
@@ -1335,7 +1346,14 @@
1335
1346
  "type": "number"
1336
1347
  },
1337
1348
  "title": {
1338
- "type": "string"
1349
+ "anyOf": [
1350
+ {
1351
+ "type": "string"
1352
+ },
1353
+ {
1354
+ "$ref": "#/definitions/Title"
1355
+ }
1356
+ ]
1339
1357
  },
1340
1358
  "transform": {
1341
1359
  "items": {
@@ -1624,7 +1642,14 @@
1624
1642
  "type": "object"
1625
1643
  },
1626
1644
  "title": {
1627
- "type": "string"
1645
+ "anyOf": [
1646
+ {
1647
+ "type": "string"
1648
+ },
1649
+ {
1650
+ "$ref": "#/definitions/Title"
1651
+ }
1652
+ ]
1628
1653
  },
1629
1654
  "transform": {
1630
1655
  "items": {
@@ -1633,7 +1658,7 @@
1633
1658
  "type": "array"
1634
1659
  },
1635
1660
  "view": {
1636
- "$ref": "#/definitions/ViewConfig"
1661
+ "$ref": "#/definitions/ViewBackground"
1637
1662
  },
1638
1663
  "visible": {
1639
1664
  "description": "Visibility of the view. An invisible view is removed from the layout and not rendered.\n\n**Default:** `true`",
@@ -2972,7 +2997,14 @@
2972
2997
  "type": "object"
2973
2998
  },
2974
2999
  "title": {
2975
- "type": "string"
3000
+ "anyOf": [
3001
+ {
3002
+ "type": "string"
3003
+ },
3004
+ {
3005
+ "$ref": "#/definitions/Title"
3006
+ }
3007
+ ]
2976
3008
  },
2977
3009
  "transform": {
2978
3010
  "items": {
@@ -2981,7 +3013,7 @@
2981
3013
  "type": "array"
2982
3014
  },
2983
3015
  "view": {
2984
- "$ref": "#/definitions/ViewConfig"
3016
+ "$ref": "#/definitions/ViewBackground"
2985
3017
  },
2986
3018
  "visible": {
2987
3019
  "description": "Visibility of the view. An invisible view is removed from the layout and not rendered.\n\n**Default:** `true`",
@@ -3137,7 +3169,14 @@
3137
3169
  "type": "object"
3138
3170
  },
3139
3171
  "title": {
3140
- "type": "string"
3172
+ "anyOf": [
3173
+ {
3174
+ "type": "string"
3175
+ },
3176
+ {
3177
+ "$ref": "#/definitions/Title"
3178
+ }
3179
+ ]
3141
3180
  },
3142
3181
  "transform": {
3143
3182
  "items": {
@@ -3146,7 +3185,7 @@
3146
3185
  "type": "array"
3147
3186
  },
3148
3187
  "view": {
3149
- "$ref": "#/definitions/ViewConfig"
3188
+ "$ref": "#/definitions/ViewBackground"
3150
3189
  },
3151
3190
  "visible": {
3152
3191
  "description": "Visibility of the view. An invisible view is removed from the layout and not rendered.\n\n**Default:** `true`",
@@ -3292,7 +3331,14 @@
3292
3331
  "type": "boolean"
3293
3332
  },
3294
3333
  "title": {
3295
- "type": "string"
3334
+ "anyOf": [
3335
+ {
3336
+ "type": "string"
3337
+ },
3338
+ {
3339
+ "$ref": "#/definitions/Title"
3340
+ }
3341
+ ]
3296
3342
  },
3297
3343
  "transform": {
3298
3344
  "items": {
@@ -3432,7 +3478,14 @@
3432
3478
  "type": "number"
3433
3479
  },
3434
3480
  "title": {
3435
- "type": "string"
3481
+ "anyOf": [
3482
+ {
3483
+ "type": "string"
3484
+ },
3485
+ {
3486
+ "$ref": "#/definitions/Title"
3487
+ }
3488
+ ]
3436
3489
  },
3437
3490
  "transform": {
3438
3491
  "items": {
@@ -3597,7 +3650,14 @@
3597
3650
  "type": "number"
3598
3651
  },
3599
3652
  "title": {
3600
- "type": "string"
3653
+ "anyOf": [
3654
+ {
3655
+ "type": "string"
3656
+ },
3657
+ {
3658
+ "$ref": "#/definitions/Title"
3659
+ }
3660
+ ]
3601
3661
  },
3602
3662
  "transform": {
3603
3663
  "items": {
@@ -3641,6 +3701,9 @@
3641
3701
  "baseUrl": {
3642
3702
  "type": "string"
3643
3703
  },
3704
+ "columns": {
3705
+ "type": "number"
3706
+ },
3644
3707
  "concat": {
3645
3708
  "items": {
3646
3709
  "anyOf": [
@@ -3749,7 +3812,14 @@
3749
3812
  "type": "number"
3750
3813
  },
3751
3814
  "title": {
3752
- "type": "string"
3815
+ "anyOf": [
3816
+ {
3817
+ "type": "string"
3818
+ },
3819
+ {
3820
+ "$ref": "#/definitions/Title"
3821
+ }
3822
+ ]
3753
3823
  },
3754
3824
  "transform": {
3755
3825
  "items": {
@@ -3780,6 +3850,7 @@
3780
3850
  }
3781
3851
  },
3782
3852
  "required": [
3853
+ "columns",
3783
3854
  "concat"
3784
3855
  ],
3785
3856
  "type": "object"
@@ -3947,7 +4018,14 @@
3947
4018
  "type": "boolean"
3948
4019
  },
3949
4020
  "title": {
3950
- "type": "string"
4021
+ "anyOf": [
4022
+ {
4023
+ "type": "string"
4024
+ },
4025
+ {
4026
+ "$ref": "#/definitions/Title"
4027
+ }
4028
+ ]
3951
4029
  },
3952
4030
  "transform": {
3953
4031
  "items": {
@@ -4062,10 +4140,6 @@
4062
4140
  "description": "The exponent of the `pow` scale.",
4063
4141
  "type": "number"
4064
4142
  },
4065
- "fp64": {
4066
- "description": "Use emulated 64bit floating points on the GPU to increase precision.\n\nEmulation has a performance cost when compared to the native 32bit processing, but the effect is negligible in the most cases.\n\n__Default value:__ `true` for `\"locus\"` scale, `false` for others.",
4067
- "type": "boolean"
4068
- },
4069
4143
  "interpolate": {
4070
4144
  "anyOf": [
4071
4145
  {
@@ -4502,6 +4576,109 @@
4502
4576
  }
4503
4577
  ]
4504
4578
  },
4579
+ "Title": {
4580
+ "additionalProperties": false,
4581
+ "properties": {
4582
+ "align": {
4583
+ "$ref": "#/definitions/Align",
4584
+ "description": "Horizontal text alignment for title text. One of `\"left\"`, `\"center\"`, or `\"right\"`."
4585
+ },
4586
+ "anchor": {
4587
+ "$ref": "#/definitions/TitleAnchor",
4588
+ "description": "The anchor position for placing the title and subtitle text. One of `\"start\"`, `\"middle\"`, or `\"end\"`. For example, with an orientation of top these anchor positions map to a left-, center-, or right-aligned title."
4589
+ },
4590
+ "angle": {
4591
+ "description": "Angle in degrees of title and subtitle text.",
4592
+ "type": "number"
4593
+ },
4594
+ "baseline": {
4595
+ "$ref": "#/definitions/Baseline",
4596
+ "description": "Vertical text baseline for title and subtitle text. One of `\"alphabetic\"` (default), `\"top\"`, `\"middle\"`, or `\"bottom\"`."
4597
+ },
4598
+ "color": {
4599
+ "description": "Text color for title text.",
4600
+ "type": "string"
4601
+ },
4602
+ "dx": {
4603
+ "description": "Delta offset for title and subtitle text x-coordinate.",
4604
+ "type": "number"
4605
+ },
4606
+ "dy": {
4607
+ "description": "Delta offset for title and subtitle text y-coordinate.",
4608
+ "type": "number"
4609
+ },
4610
+ "font": {
4611
+ "description": "Font name for title text.",
4612
+ "type": "string"
4613
+ },
4614
+ "fontSize": {
4615
+ "description": "Font size in pixels for title text.",
4616
+ "minimum": 0,
4617
+ "type": "number"
4618
+ },
4619
+ "fontStyle": {
4620
+ "$ref": "#/definitions/FontStyle",
4621
+ "description": "Font style for title text."
4622
+ },
4623
+ "fontWeight": {
4624
+ "$ref": "#/definitions/FontWeight",
4625
+ "description": "Font weight for title text. This can be either a string (e.g `\"bold\"`, `\"normal\"`) or a number (`100`, `200`, `300`, ..., `900` where `\"normal\"` = `400` and `\"bold\"` = `700`)."
4626
+ },
4627
+ "frame": {
4628
+ "$ref": "#/definitions/TitleFrame",
4629
+ "description": "The reference frame for the anchor position, one of `\"bounds\"` (to anchor relative to the full bounding box) or `\"group\"` (to anchor relative to the group width or height)."
4630
+ },
4631
+ "offset": {
4632
+ "description": "The orthogonal offset in pixels by which to displace the title group from its position along the edge of the chart.",
4633
+ "type": "number"
4634
+ },
4635
+ "orient": {
4636
+ "$ref": "#/definitions/TitleOrient",
4637
+ "description": "Default title orientation (`\"top\"`, `\"bottom\"`, `\"left\"`, or `\"right\"`)"
4638
+ },
4639
+ "style": {
4640
+ "description": "A mark style property to apply to the title text mark. If not specified, a default style of `\"group-title\"` is applied.",
4641
+ "type": "string"
4642
+ },
4643
+ "text": {
4644
+ "description": "The title text.",
4645
+ "type": "string"
4646
+ }
4647
+ },
4648
+ "required": [
4649
+ "text"
4650
+ ],
4651
+ "type": "object"
4652
+ },
4653
+ "TitleAnchor": {
4654
+ "enum": [
4655
+ null,
4656
+ "start",
4657
+ "middle",
4658
+ "end"
4659
+ ],
4660
+ "type": [
4661
+ "null",
4662
+ "string"
4663
+ ]
4664
+ },
4665
+ "TitleFrame": {
4666
+ "enum": [
4667
+ "bounds",
4668
+ "group"
4669
+ ],
4670
+ "type": "string"
4671
+ },
4672
+ "TitleOrient": {
4673
+ "enum": [
4674
+ "none",
4675
+ "left",
4676
+ "right",
4677
+ "top",
4678
+ "bottom"
4679
+ ],
4680
+ "type": "string"
4681
+ },
4505
4682
  "Tooltip": {
4506
4683
  "anyOf": [
4507
4684
  {
@@ -4700,7 +4877,14 @@
4700
4877
  "type": "object"
4701
4878
  },
4702
4879
  "title": {
4703
- "type": "string"
4880
+ "anyOf": [
4881
+ {
4882
+ "type": "string"
4883
+ },
4884
+ {
4885
+ "$ref": "#/definitions/Title"
4886
+ }
4887
+ ]
4704
4888
  },
4705
4889
  "transform": {
4706
4890
  "items": {
@@ -4709,7 +4893,7 @@
4709
4893
  "type": "array"
4710
4894
  },
4711
4895
  "view": {
4712
- "$ref": "#/definitions/ViewConfig"
4896
+ "$ref": "#/definitions/ViewBackground"
4713
4897
  },
4714
4898
  "visible": {
4715
4899
  "description": "Visibility of the view. An invisible view is removed from the layout and not rendered.\n\n**Default:** `true`",
@@ -4859,7 +5043,14 @@
4859
5043
  "type": "number"
4860
5044
  },
4861
5045
  "title": {
4862
- "type": "string"
5046
+ "anyOf": [
5047
+ {
5048
+ "type": "string"
5049
+ },
5050
+ {
5051
+ "$ref": "#/definitions/Title"
5052
+ }
5053
+ ]
4863
5054
  },
4864
5055
  "transform": {
4865
5056
  "items": {
@@ -4936,7 +5127,7 @@
4936
5127
  ],
4937
5128
  "type": "object"
4938
5129
  },
4939
- "ViewConfig": {
5130
+ "ViewBackground": {
4940
5131
  "additionalProperties": false,
4941
5132
  "properties": {
4942
5133
  "cornerRadius": {
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "contributors": [],
9
9
  "license": "BSD-2-Clause",
10
- "version": "0.18.1",
10
+ "version": "0.20.0",
11
11
  "main": "dist/index.js",
12
12
  "module": "src/index.js",
13
13
  "exports": {
@@ -28,6 +28,7 @@
28
28
  "dev": "node dev-server.js",
29
29
  "build": "vite build && npm run build:schema",
30
30
  "prepublishOnly": "npm run build",
31
+ "test:vitest": "vitest run",
31
32
  "test:tsc": "tsc -p tsconfig.json",
32
33
  "checkSpec": "tsc --allowJs --checkJs --strict --noEmit --moduleResolution node --target es6 src/spec/root.d.ts",
33
34
  "build:schema": "mkdir -p dist && ts-json-schema-generator --path 'src/spec/*.ts' --type RootSpec > dist/schema.json"
@@ -43,7 +44,7 @@
43
44
  "d3-color": "^3.0.1",
44
45
  "d3-ease": "^3.0.1",
45
46
  "d3-format": "^3.0.1",
46
- "flatqueue": "^1.2.1",
47
+ "flatqueue": "^2.0.3",
47
48
  "internmap": "^2.0.3",
48
49
  "lit-html": "^2.0.2",
49
50
  "twgl.js": "^4.19.1",
@@ -52,5 +53,5 @@
52
53
  "vega-scale": "^7.1.1",
53
54
  "vega-util": "^1.16.0"
54
55
  },
55
- "gitHead": "5f4867844fa8b52f5e7df41b72be698550777f94"
56
+ "gitHead": "dfeadc37891908cf775423c61a566358ecada9fa"
56
57
  }
@@ -27,7 +27,7 @@ export default class Collector extends FlowNode {
27
27
  /** @type {(function(Collector):void)[]} */
28
28
  this.observers = [];
29
29
 
30
- /** @type {Map<any | any[], Data>} */
30
+ /** @type {Map<any | any[], Data>} TODO: proper type for key */
31
31
  this.facetBatches = undefined;
32
32
 
33
33
  this._init();
@@ -59,8 +59,6 @@ export default class Collector extends FlowNode {
59
59
  * @param {import("./flowBatch").FlowBatch} flowBatch
60
60
  */
61
61
  beginBatch(flowBatch) {
62
- // TODO: Propagate batches to children(?)
63
-
64
62
  if (isFacetBatch(flowBatch)) {
65
63
  this._data = [];
66
64
  this.facetBatches.set(asArray(flowBatch.facetId), this._data);
@@ -103,7 +101,14 @@ export default class Collector extends FlowNode {
103
101
  }
104
102
 
105
103
  if (this.children.length) {
106
- for (const data of this.facetBatches.values()) {
104
+ for (const [key, data] of this.facetBatches.entries()) {
105
+ if (key) {
106
+ /** @type {import("./flowBatch").FacetBatch} */
107
+ const facetBatch = { type: "facet", facetId: key };
108
+ for (const child of this.children) {
109
+ child.beginBatch(facetBatch);
110
+ }
111
+ }
107
112
  for (const datum of data) {
108
113
  this._propagate(datum);
109
114
  }
@@ -1,3 +1,5 @@
1
+ import { expect, test } from "vitest";
2
+
1
3
  import Collector from "./collector";
2
4
 
3
5
  const data = [1, 5, 2, 4, 3].map((x) => ({ x }));
@@ -1,3 +1,5 @@
1
+ import { describe, test } from "vitest";
2
+
1
3
  describe("DataFlow", () => {
2
4
  test.todo("TODO");
3
5
  });
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test } from "vitest";
1
2
  import FilterTransform from "./transforms/filter";
2
3
  import FormulaTransform from "./transforms/formula";
3
4
  import Collector from "./collector";
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test } from "vitest";
1
2
  import FlowNode from "./flowNode";
2
3
  import { validateLinks } from "./flowOptimizer";
3
4
 
@@ -1,3 +1,4 @@
1
+ import Collector from "./collector";
1
2
  import { BEHAVIOR_CLONES } from "./flowNode";
2
3
  import CloneTransform from "./transforms/clone";
3
4
 
@@ -31,6 +32,11 @@ export function validateLinks(node, parent = undefined) {
31
32
  * @param {FlowNode} node
32
33
  */
33
34
  export function removeRedundantCloneTransforms(node, cloneRequired = false) {
35
+ if (node instanceof Collector) {
36
+ // If an object is modified downstream of Collector, it must be cloned
37
+ cloneRequired = true;
38
+ }
39
+
34
40
  if (node instanceof CloneTransform) {
35
41
  if (cloneRequired) {
36
42
  cloneRequired = false;
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test } from "vitest";
1
2
  import FlowNode, { BEHAVIOR_CLONES } from "./flowNode";
2
3
  import { removeRedundantCloneTransforms, validateLinks } from "./flowOptimizer";
3
4
  import CloneTransform from "./transforms/clone";
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import fasta from "./fasta";
2
3
 
3
4
  test("fasta", () => {
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import Collector from "../collector";
2
3
  import InlineSource from "./inlineSource";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import Collector from "../collector";
2
3
  import SequenceSource from "./sequenceSource";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
  import CloneTransform from "./clone";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import CoverageTransform from "./coverage";
2
3
  import { processData } from "../flowTestUtils";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
  import FilterTransform from "./filter";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
  import FlattenDelimitedTransform from "./flattenDelimited";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
  import FlattenSequenceTransform from "./flattenSequence";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
  import FormulaTransform from "./formula";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import { range } from "d3-array";
2
3
  import { processData } from "../flowTestUtils";
3
4
  import IdentifierTransform, { BLOCK_SIZE, DEFAULT_AS } from "./identifier";
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import PileupTransform from "./pileup";
2
3
  import { processData } from "../flowTestUtils";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
  import ProjectTransform from "./project";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
 
3
4
  import RegexExtractTransform from "./regexExtract";
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
  import RegexFoldTransform from "./regexFold";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import SampleTransform from "./sample";
2
3
  import { extent } from "d3-array";
3
4
  import { createChain } from "../../view/flowBuilder";
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test } from "vitest";
1
2
  import { processData } from "../flowTestUtils";
2
3
  import StackTransform from "./stack";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { expect, test } from "vitest";
1
2
  import AccessorFactory from "./accessor";
2
3
 
3
4
  const af = new AccessorFactory();
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test } from "vitest";
1
2
  import AccessorFactory from "./accessor";
2
3
  import { scale as vegaScale } from "vega-scale";
3
4
 
@@ -257,15 +257,27 @@ export default class Genome {
257
257
  parseInterval(str) {
258
258
  // TODO: consider changing [0-9XY] to support other species besides humans
259
259
  const matches = str.match(
260
- /^(chr[0-9A-Z]+):([0-9,]+)-(?:(chr[0-9A-Z]+):)?([0-9,]+)$/
260
+ /^(chr[0-9A-Z]+)(?::([0-9,]+)(?:-(?:(chr[0-9A-Z]+):)?([0-9,]+))?)?$/
261
261
  );
262
262
 
263
263
  if (matches) {
264
264
  const startChr = matches[1];
265
+
266
+ if (matches.slice(2).every((x) => x === undefined)) {
267
+ const chrom = this.getChromosome(startChr);
268
+ if (chrom) {
269
+ return [chrom.continuousStart, chrom.continuousEnd];
270
+ }
271
+ return;
272
+ }
273
+
265
274
  const endChr = matches[3] || startChr;
266
275
 
267
276
  const startIndex = parseInt(matches[2].replace(/,/g, ""));
268
- const endIndex = parseInt(matches[4].replace(/,/g, ""));
277
+ const endIndex =
278
+ matches[4] !== undefined
279
+ ? parseInt(matches[4].replace(/,/g, ""))
280
+ : startIndex;
269
281
 
270
282
  return [
271
283
  this.toContinuous(startChr, startIndex - 1),