@genome-spy/core 0.30.0 → 0.30.2

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 (234) hide show
  1. package/dist/index.es.js +16373 -0
  2. package/dist/index.js +43 -43
  3. package/package.json +10 -7
  4. package/src/data/collector.js +0 -183
  5. package/src/data/collector.test.js +0 -84
  6. package/src/data/dataFlow.js +0 -148
  7. package/src/data/dataFlow.test.js +0 -5
  8. package/src/data/facetNode.js +0 -17
  9. package/src/data/flow.test.js +0 -72
  10. package/src/data/flowBatch.d.ts +0 -40
  11. package/src/data/flowNode.js +0 -283
  12. package/src/data/flowNode.test.js +0 -50
  13. package/src/data/flowOptimizer.js +0 -123
  14. package/src/data/flowOptimizer.test.js +0 -193
  15. package/src/data/flowTestUtils.js +0 -63
  16. package/src/data/formats/fasta.js +0 -32
  17. package/src/data/formats/fasta.test.js +0 -27
  18. package/src/data/sources/dataSource.js +0 -22
  19. package/src/data/sources/dataSourceFactory.js +0 -24
  20. package/src/data/sources/dataUtils.js +0 -78
  21. package/src/data/sources/dynamicCallbackSource.js +0 -57
  22. package/src/data/sources/dynamicSource.js +0 -37
  23. package/src/data/sources/inlineSource.js +0 -67
  24. package/src/data/sources/inlineSource.test.js +0 -56
  25. package/src/data/sources/namedSource.js +0 -79
  26. package/src/data/sources/sequenceSource.js +0 -46
  27. package/src/data/sources/sequenceSource.test.js +0 -46
  28. package/src/data/sources/urlSource.js +0 -74
  29. package/src/data/transforms/aggregate.js +0 -70
  30. package/src/data/transforms/clone.js +0 -40
  31. package/src/data/transforms/clone.test.js +0 -11
  32. package/src/data/transforms/coverage.js +0 -187
  33. package/src/data/transforms/coverage.test.js +0 -123
  34. package/src/data/transforms/filter.js +0 -37
  35. package/src/data/transforms/filter.test.js +0 -18
  36. package/src/data/transforms/filterScoredLabels.js +0 -134
  37. package/src/data/transforms/flattenCompressedExons.js +0 -57
  38. package/src/data/transforms/flattenDelimited.js +0 -74
  39. package/src/data/transforms/flattenDelimited.test.js +0 -87
  40. package/src/data/transforms/flattenSequence.js +0 -39
  41. package/src/data/transforms/flattenSequence.test.js +0 -34
  42. package/src/data/transforms/formula.js +0 -39
  43. package/src/data/transforms/formula.test.js +0 -19
  44. package/src/data/transforms/identifier.js +0 -108
  45. package/src/data/transforms/identifier.test.js +0 -83
  46. package/src/data/transforms/linearizeGenomicCoordinate.js +0 -101
  47. package/src/data/transforms/measureText.js +0 -44
  48. package/src/data/transforms/pileup.js +0 -128
  49. package/src/data/transforms/pileup.test.js +0 -70
  50. package/src/data/transforms/project.js +0 -41
  51. package/src/data/transforms/project.test.js +0 -32
  52. package/src/data/transforms/regexExtract.js +0 -61
  53. package/src/data/transforms/regexExtract.test.js +0 -67
  54. package/src/data/transforms/regexFold.js +0 -141
  55. package/src/data/transforms/regexFold.test.js +0 -160
  56. package/src/data/transforms/sample.js +0 -101
  57. package/src/data/transforms/sample.test.js +0 -38
  58. package/src/data/transforms/stack.js +0 -137
  59. package/src/data/transforms/stack.test.js +0 -91
  60. package/src/data/transforms/transformFactory.js +0 -60
  61. package/src/embedApi.d.ts +0 -67
  62. package/src/encoder/accessor.js +0 -82
  63. package/src/encoder/accessor.test.js +0 -47
  64. package/src/encoder/encoder.js +0 -394
  65. package/src/encoder/encoder.test.js +0 -98
  66. package/src/fonts/Lato-Regular.json +0 -1267
  67. package/src/fonts/Lato-Regular.png +0 -0
  68. package/src/fonts/OFL.txt +0 -93
  69. package/src/fonts/README.md +0 -3
  70. package/src/fonts/bmFont.d.ts +0 -58
  71. package/src/fonts/bmFontManager.js +0 -357
  72. package/src/fonts/bmFontMetrics.js +0 -108
  73. package/src/genome/genome.js +0 -317
  74. package/src/genome/genome.test.js +0 -188
  75. package/src/genome/genomeStore.js +0 -54
  76. package/src/genome/locusFormat.js +0 -31
  77. package/src/genome/scaleIndex.d.ts +0 -38
  78. package/src/genome/scaleIndex.js +0 -166
  79. package/src/genome/scaleIndex.test.js +0 -78
  80. package/src/genome/scaleLocus.d.ts +0 -11
  81. package/src/genome/scaleLocus.js +0 -108
  82. package/src/genome/scaleLocus.test.js +0 -4
  83. package/src/genomeSpy.js +0 -785
  84. package/src/gl/arrayBuilder.js +0 -199
  85. package/src/gl/dataToVertices.js +0 -636
  86. package/src/gl/includes/common.glsl +0 -63
  87. package/src/gl/includes/picking.fragment.glsl +0 -1
  88. package/src/gl/includes/picking.vertex.glsl +0 -27
  89. package/src/gl/includes/sampleFacet.glsl +0 -107
  90. package/src/gl/includes/scales.glsl +0 -112
  91. package/src/gl/link.fragment.glsl +0 -18
  92. package/src/gl/link.vertex.glsl +0 -111
  93. package/src/gl/point.fragment.glsl +0 -123
  94. package/src/gl/point.vertex.glsl +0 -129
  95. package/src/gl/rect.fragment.glsl +0 -51
  96. package/src/gl/rect.vertex.glsl +0 -114
  97. package/src/gl/rule.fragment.glsl +0 -52
  98. package/src/gl/rule.vertex.glsl +0 -89
  99. package/src/gl/text.fragment.glsl +0 -31
  100. package/src/gl/text.vertex.glsl +0 -246
  101. package/src/gl/webGLHelper.js +0 -504
  102. package/src/img/bowtie.svg +0 -1
  103. package/src/img/genomespy-favicon.svg +0 -34
  104. package/src/index.html +0 -11
  105. package/src/index.js +0 -128
  106. package/src/marks/link.js +0 -175
  107. package/src/marks/mark.js +0 -975
  108. package/src/marks/markUtils.js +0 -125
  109. package/src/marks/pointMark.js +0 -251
  110. package/src/marks/rectMark.js +0 -241
  111. package/src/marks/rule.js +0 -250
  112. package/src/marks/text.js +0 -278
  113. package/src/node_modules/.vitest/results.json +0 -1
  114. package/src/scale/colorUtils.js +0 -184
  115. package/src/scale/glslScaleGenerator.js +0 -502
  116. package/src/scale/scale.js +0 -451
  117. package/src/scale/scale.test.js +0 -324
  118. package/src/scale/ticks.js +0 -203
  119. package/src/scale/ticks.test.js +0 -40
  120. package/src/singlePageApp.js +0 -13
  121. package/src/spec/axis.d.ts +0 -296
  122. package/src/spec/channel.d.ts +0 -430
  123. package/src/spec/data.d.ts +0 -196
  124. package/src/spec/font.d.ts +0 -15
  125. package/src/spec/genome.d.ts +0 -35
  126. package/src/spec/mark.d.ts +0 -429
  127. package/src/spec/root.d.ts +0 -17
  128. package/src/spec/sampleView.d.ts +0 -180
  129. package/src/spec/scale.d.ts +0 -273
  130. package/src/spec/title.d.ts +0 -102
  131. package/src/spec/tooltip.d.ts +0 -9
  132. package/src/spec/transform.d.ts +0 -479
  133. package/src/spec/view.d.ts +0 -201
  134. package/src/styles/genome-spy.scss +0 -153
  135. package/src/tooltip/dataTooltipHandler.js +0 -64
  136. package/src/tooltip/refseqGeneTooltipHandler.js +0 -78
  137. package/src/tooltip/tooltipHandler.ts +0 -12
  138. package/src/types/filetypes.d.ts +0 -14
  139. package/src/types/flatqueue.d.ts +0 -53
  140. package/src/types/glsl.d.ts +0 -4
  141. package/src/types/internmap.d.ts +0 -22
  142. package/src/types/object.d.ts +0 -21
  143. package/src/types/vega-loader.d.ts +0 -1
  144. package/src/types/vega-scale.d.ts +0 -60
  145. package/src/utils/addBaseUrl.js +0 -19
  146. package/src/utils/addBaseUrl.test.js +0 -22
  147. package/src/utils/animator.js +0 -83
  148. package/src/utils/arrayUtils.js +0 -61
  149. package/src/utils/binnedIndex.js +0 -167
  150. package/src/utils/binnedIndex.test.js +0 -155
  151. package/src/utils/clamp.js +0 -8
  152. package/src/utils/cloner.js +0 -34
  153. package/src/utils/cloner.test.js +0 -24
  154. package/src/utils/coalesce.js +0 -11
  155. package/src/utils/coalesce.test.js +0 -16
  156. package/src/utils/concatIterables.js +0 -26
  157. package/src/utils/concatIterables.test.js +0 -8
  158. package/src/utils/debounce.js +0 -37
  159. package/src/utils/domainArray.js +0 -216
  160. package/src/utils/domainArray.test.js +0 -130
  161. package/src/utils/eerp.js +0 -13
  162. package/src/utils/expression.js +0 -32
  163. package/src/utils/field.js +0 -28
  164. package/src/utils/formatObject.js +0 -31
  165. package/src/utils/indexer.js +0 -43
  166. package/src/utils/indexer.test.js +0 -47
  167. package/src/utils/inertia.js +0 -124
  168. package/src/utils/interactionEvent.js +0 -33
  169. package/src/utils/iterateNestedMaps.js +0 -21
  170. package/src/utils/iterateNestedMaps.test.js +0 -33
  171. package/src/utils/kWayMerge.js +0 -42
  172. package/src/utils/kWayMerge.test.js +0 -26
  173. package/src/utils/layout/flexLayout.js +0 -368
  174. package/src/utils/layout/flexLayout.test.js +0 -311
  175. package/src/utils/layout/grid.js +0 -95
  176. package/src/utils/layout/grid.test.js +0 -71
  177. package/src/utils/layout/padding.js +0 -120
  178. package/src/utils/layout/point.js +0 -23
  179. package/src/utils/layout/rectangle.js +0 -288
  180. package/src/utils/layout/rectangle.test.js +0 -172
  181. package/src/utils/mergeObjects.js +0 -99
  182. package/src/utils/mergeObjects.test.js +0 -42
  183. package/src/utils/numberExtractor.js +0 -24
  184. package/src/utils/numberExtractor.test.js +0 -6
  185. package/src/utils/point.js +0 -14
  186. package/src/utils/propertyCacher.js +0 -70
  187. package/src/utils/propertyCacher.test.js +0 -85
  188. package/src/utils/propertyCoalescer.js +0 -42
  189. package/src/utils/propertyCoalescer.test.js +0 -22
  190. package/src/utils/reservationMap.js +0 -103
  191. package/src/utils/reservationMap.test.js +0 -20
  192. package/src/utils/scaleNull.js +0 -19
  193. package/src/utils/setOperations.js +0 -75
  194. package/src/utils/smoothstep.js +0 -10
  195. package/src/utils/throttle.js +0 -34
  196. package/src/utils/topK.js +0 -76
  197. package/src/utils/topK.test.js +0 -64
  198. package/src/utils/transition.js +0 -74
  199. package/src/utils/ui/tooltip.js +0 -189
  200. package/src/utils/url.js +0 -22
  201. package/src/utils/variableTools.js +0 -24
  202. package/src/utils/variableTools.test.js +0 -13
  203. package/src/view/axisResolution.js +0 -140
  204. package/src/view/axisResolution.test.js +0 -201
  205. package/src/view/axisView.js +0 -747
  206. package/src/view/concatView.js +0 -45
  207. package/src/view/containerView.js +0 -159
  208. package/src/view/facetView.js +0 -491
  209. package/src/view/flowBuilder.js +0 -367
  210. package/src/view/flowBuilder.test.js +0 -125
  211. package/src/view/gridView.js +0 -786
  212. package/src/view/implicitRootView.js +0 -14
  213. package/src/view/importView.js +0 -19
  214. package/src/view/layerView.js +0 -74
  215. package/src/view/rendering.d.ts +0 -44
  216. package/src/view/renderingContext/compositeViewRenderingContext.js +0 -51
  217. package/src/view/renderingContext/deferredViewRenderingContext.js +0 -176
  218. package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
  219. package/src/view/renderingContext/simpleViewRenderingContext.js +0 -64
  220. package/src/view/renderingContext/svgViewRenderingContext.js +0 -125
  221. package/src/view/renderingContext/viewRenderingContext.js +0 -41
  222. package/src/view/scaleResolution.js +0 -797
  223. package/src/view/scaleResolution.test.js +0 -572
  224. package/src/view/scaleResolutionApi.d.ts +0 -40
  225. package/src/view/testUtils.js +0 -51
  226. package/src/view/title.js +0 -165
  227. package/src/view/unitView.js +0 -382
  228. package/src/view/view.js +0 -612
  229. package/src/view/view.test.js +0 -214
  230. package/src/view/viewContext.d.ts +0 -62
  231. package/src/view/viewFactory.js +0 -181
  232. package/src/view/viewFactory.test.js +0 -17
  233. package/src/view/viewUtils.js +0 -327
  234. package/src/view/zoom.js +0 -89
@@ -1,74 +0,0 @@
1
- import { asArray } from "../../utils/arrayUtils";
2
- import { field } from "../../utils/field";
3
- import FlowNode, { BEHAVIOR_CLONES } from "../flowNode";
4
-
5
- /**
6
- * @typedef {import("../../spec/transform").FlattenDelimitedParams} FlattenDelimitedParams
7
- * @prop {string[]} separators
8
- * @prop {string[]} fields
9
- * @prop {string[]} [as]
10
- */
11
-
12
- export default class FlattenDelimitedTransform extends FlowNode {
13
- get behavior() {
14
- return BEHAVIOR_CLONES;
15
- }
16
-
17
- /**
18
- *
19
- * @param {FlattenDelimitedParams} params
20
- */
21
- constructor(params) {
22
- super();
23
-
24
- // TODO: Validate config. string elements, etc...
25
-
26
- const accessors = asArray(params.field).map((f) => field(f));
27
- const separators = asArray(params.separator);
28
- const as = asArray(params.as || params.field);
29
-
30
- if (
31
- accessors.length !== separators.length ||
32
- accessors.length !== as.length
33
- ) {
34
- throw new Error(
35
- `Lengths of "separator" (${separators.length}), "fields" (${accessors.length}), and "as" (${as.length}) do not match!`
36
- );
37
- }
38
-
39
- /** @param {any[]} datum */
40
- this.handle = (datum) => {
41
- if (accessors.some((a) => !a(datum))) return;
42
-
43
- const splitFields = accessors.map((accessor, i) =>
44
- accessor(datum).split(separators[i])
45
- );
46
- validateSplit(splitFields, datum);
47
- const flatLen = splitFields[0].length;
48
-
49
- for (let ri = 0; ri < flatLen; ri++) {
50
- /** @type {import("../flowNode").Datum} */
51
- const newRow = Object.assign({}, datum);
52
- for (let fi = 0; fi < accessors.length; fi++) {
53
- newRow[as[fi]] = splitFields[fi][ri];
54
- }
55
- this._propagate(newRow);
56
- }
57
- };
58
- }
59
- }
60
-
61
- /**
62
- *
63
- * @param {any[]} splitFields
64
- * @param {unknown} row
65
- */
66
- function validateSplit(splitFields, row) {
67
- const splitLengths = splitFields.map((f) => f.length);
68
- if (!splitLengths.every((x) => x == splitLengths[0])) {
69
- throw new Error(
70
- "Mismatching number of elements in the fields to be split: " +
71
- JSON.stringify(row)
72
- );
73
- }
74
- }
@@ -1,87 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { processData } from "../flowTestUtils";
3
- import FlattenDelimitedTransform from "./flattenDelimited";
4
-
5
- const sampleData = [
6
- { id: 1, a: "q, w, e", b: "a-s-d" },
7
- { id: 2, a: "r, t, y", b: "f-g-h" },
8
- { id: 3, a: "u", b: "j" },
9
- ];
10
-
11
- /**
12
- * @param {import("./flattenDelimited").FlattenDelimitedParams} params
13
- * @param {any[]} data
14
- */
15
- function transform(params, data) {
16
- return processData(new FlattenDelimitedTransform(params), data);
17
- }
18
-
19
- describe("FlattenDelimited transform", () => {
20
- test("With a single field", () => {
21
- /** @type {import("./flattenDelimited").FlattenDelimitedParams} */
22
- const config = {
23
- type: "flattenDelimited",
24
- field: "a",
25
- separator: ", ",
26
- };
27
-
28
- expect(transform(config, sampleData)).toEqual([
29
- { id: 1, a: "q", b: "a-s-d" },
30
- { id: 1, a: "w", b: "a-s-d" },
31
- { id: 1, a: "e", b: "a-s-d" },
32
- { id: 2, a: "r", b: "f-g-h" },
33
- { id: 2, a: "t", b: "f-g-h" },
34
- { id: 2, a: "y", b: "f-g-h" },
35
- { id: 3, a: "u", b: "j" },
36
- ]);
37
- });
38
-
39
- test("With two fields", () => {
40
- /** @type {import("./flattenDelimited").FlattenDelimitedParams} */
41
- const config = {
42
- type: "flattenDelimited",
43
- field: ["a", "b"],
44
- as: ["a", "c"],
45
- separator: [", ", "-"],
46
- };
47
-
48
- expect(transform(config, sampleData)).toEqual([
49
- { id: 1, a: "q", b: "a-s-d", c: "a" },
50
- { id: 1, a: "w", b: "a-s-d", c: "s" },
51
- { id: 1, a: "e", b: "a-s-d", c: "d" },
52
- { id: 2, a: "r", b: "f-g-h", c: "f" },
53
- { id: 2, a: "t", b: "f-g-h", c: "g" },
54
- { id: 2, a: "y", b: "f-g-h", c: "h" },
55
- { id: 3, a: "u", b: "j", c: "j" },
56
- ]);
57
- });
58
-
59
- test("Throws on differing field lengths", () => {
60
- const data = [
61
- {
62
- a: "1-2",
63
- b: "1-2-3",
64
- },
65
- ];
66
-
67
- /** @type {import("./flattenDelimited").FlattenDelimitedParams} */
68
- const config = {
69
- type: "flattenDelimited",
70
- field: ["a", "b"],
71
- separator: ["-", "-"],
72
- };
73
-
74
- expect(() => transform(config, data)).toThrow();
75
- });
76
-
77
- test("Throws on mismatching spec lengths", () => {
78
- /** @type {import("./flattenDelimited").FlattenDelimitedParams} */
79
- const config = {
80
- type: "flattenDelimited",
81
- field: ["a", "b"],
82
- separator: ["a"],
83
- };
84
-
85
- expect(() => transform(config, sampleData)).toThrow();
86
- });
87
- });
@@ -1,39 +0,0 @@
1
- import { field } from "../../utils/field";
2
- import FlowNode, { BEHAVIOR_CLONES } from "../flowNode";
3
-
4
- /**
5
- * @typedef {import("../../spec/transform").FlattenSequenceParams} FlattenSequenceParams
6
- */
7
-
8
- export default class FlattenSequenceTransform extends FlowNode {
9
- get behavior() {
10
- return BEHAVIOR_CLONES;
11
- }
12
-
13
- /**
14
- *
15
- * @param {FlattenSequenceParams} params
16
- */
17
- constructor(params) {
18
- super();
19
-
20
- const accessor = field(params.field ?? "sequence");
21
- const [asPos, asSequence] = params.as ?? ["pos", "sequence"];
22
-
23
- /** @param {any[]} datum */
24
- this.handle = (datum) => {
25
- // TODO: Use code generation
26
- const template = Object.assign({}, datum, {
27
- [asSequence]: "",
28
- [asPos]: 0,
29
- });
30
- const sequence = /** @type {string} */ (accessor(datum));
31
- for (let i = 0; i < sequence.length; i++) {
32
- const newObject = Object.assign({}, template);
33
- newObject[asPos] = i;
34
- newObject[asSequence] = sequence.charAt(i);
35
- this._propagate(newObject);
36
- }
37
- };
38
- }
39
- }
@@ -1,34 +0,0 @@
1
- import { expect, test } from "vitest";
2
- import { processData } from "../flowTestUtils";
3
- import FlattenSequenceTransform from "./flattenSequence";
4
-
5
- /**
6
- * @param {import("./flattenSequence").FlattenSequenceParams} params
7
- * @param {any[]} data
8
- */
9
- function transform(params, data) {
10
- return processData(new FlattenSequenceTransform(params), data);
11
- }
12
-
13
- test("FlattenSequenece", () => {
14
- expect(
15
- transform(
16
- {
17
- type: "flattenSequence",
18
- field: "seq",
19
- as: ["p", "seq"],
20
- },
21
- [
22
- { identifier: "A", seq: "TCG" },
23
- { identifier: "B", seq: "AAT" },
24
- ]
25
- )
26
- ).toEqual([
27
- { identifier: "A", seq: "T", p: 0 },
28
- { identifier: "A", seq: "C", p: 1 },
29
- { identifier: "A", seq: "G", p: 2 },
30
- { identifier: "B", seq: "A", p: 0 },
31
- { identifier: "B", seq: "A", p: 1 },
32
- { identifier: "B", seq: "T", p: 2 },
33
- ]);
34
- });
@@ -1,39 +0,0 @@
1
- import createFunction from "../../utils/expression";
2
- import FlowNode, { BEHAVIOR_MODIFIES } from "../flowNode";
3
-
4
- /**
5
- * @typedef {import("../../spec/transform").FormulaParams} FormulaParams
6
- */
7
-
8
- export default class FormulaTransform extends FlowNode {
9
- get behavior() {
10
- return BEHAVIOR_MODIFIES;
11
- }
12
-
13
- /**
14
- *
15
- * @param {FormulaParams} params
16
- */
17
- constructor(params) {
18
- super();
19
- this.params = params;
20
-
21
- this.as = params.as;
22
-
23
- /** @type {(datum: any) => any} */
24
- this.fn = undefined;
25
- }
26
-
27
- initialize() {
28
- this.fn = createFunction(this.params.expr, this.getGlobalObject());
29
- }
30
-
31
- /**
32
- *
33
- * @param {import("../flowNode").Datum} datum
34
- */
35
- handle(datum) {
36
- datum[this.as] = this.fn(datum);
37
- this._propagate(datum);
38
- }
39
- }
@@ -1,19 +0,0 @@
1
- import { expect, test } from "vitest";
2
- import { processData } from "../flowTestUtils";
3
- import FormulaTransform from "./formula";
4
-
5
- test("FormulaTransform", () => {
6
- const data = [{ a: 2 }, { a: 3 }];
7
-
8
- const t = new FormulaTransform({
9
- type: "formula",
10
- expr: "datum.a * 2",
11
- as: "b",
12
- });
13
- t.initialize();
14
-
15
- expect(processData(t, data)).toEqual([
16
- { a: 2, b: 4 },
17
- { a: 3, b: 6 },
18
- ]);
19
- });
@@ -1,108 +0,0 @@
1
- import FlowNode, { BEHAVIOR_MODIFIES } from "../flowNode";
2
-
3
- export const DEFAULT_AS = "_uniqueId";
4
-
5
- export const BLOCK_SIZE = 10000;
6
-
7
- /**
8
- * TODO: The reservation map should be bound to GenomeSpy instances.
9
- * Because it's now global, there's a higher risk that we run out of ids.
10
- *
11
- * TODO: Identifier transforms should be removed from the reservation map
12
- * when a transform is removed from the flow.
13
- *
14
- * The first block is reserved for "none".
15
- *
16
- * @type {IdentifierTransform[]}
17
- */
18
- const reservationMap = [null];
19
-
20
- /**
21
- * Assigns unique identifiers for tuples that pass through this transform.
22
- *
23
- * The identifiers are reserved in equally sized blocks, allowing for
24
- * quick lookup of the IdentifierTransform instance that assigned the id.
25
- * This is mainly used for creating ids that can be used for picking, i.e.,
26
- * selecting rendered data items by hovering or clicking.
27
- *
28
- * @typedef {import("../../spec/transform").IdentifierParams} IdentifierParams
29
- */
30
- export default class IdentifierTransform extends FlowNode {
31
- get behavior() {
32
- return BEHAVIOR_MODIFIES;
33
- }
34
-
35
- /**
36
- *
37
- * @param {IdentifierParams} params
38
- */
39
- constructor(params) {
40
- super();
41
- this.params = params;
42
-
43
- this.as = params.as ?? DEFAULT_AS;
44
-
45
- /**
46
- * The block indexes reserved by this transform instance.
47
- * @type {number[]}
48
- */
49
- this._blocks = [];
50
-
51
- /**
52
- * The number of blocks used
53
- */
54
- this._usedBlocks = 0;
55
-
56
- /**
57
- * The next advancement allocates the initial block for this instance
58
- */
59
- this._id = -1;
60
- }
61
-
62
- initialize() {
63
- //
64
- }
65
-
66
- reset() {
67
- super.reset();
68
-
69
- this._usedBlocks = 0;
70
- this._id = -1;
71
- }
72
-
73
- /**
74
- *
75
- * @param {import("../flowNode").Datum} datum
76
- */
77
- handle(datum) {
78
- datum[this.as] = this._nextId();
79
- this._propagate(datum);
80
- }
81
-
82
- /**
83
- * @returns {number}
84
- */
85
- _nextId() {
86
- if (++this._id % BLOCK_SIZE == 0) {
87
- this._id = this._getBlock() * BLOCK_SIZE;
88
- }
89
- return this._id;
90
- }
91
-
92
- _getBlock() {
93
- if (this._usedBlocks < this._blocks.length) {
94
- return this._blocks[this._usedBlocks++];
95
- }
96
-
97
- return this._reserveBlock();
98
- }
99
-
100
- _reserveBlock() {
101
- const blockId = reservationMap.length;
102
- reservationMap[blockId] = this;
103
- this._blocks.push(blockId);
104
- this._usedBlocks++;
105
-
106
- return blockId;
107
- }
108
- }
@@ -1,83 +0,0 @@
1
- import { expect, test } from "vitest";
2
- import { range } from "d3-array";
3
- import { processData } from "../flowTestUtils";
4
- import IdentifierTransform, { BLOCK_SIZE, DEFAULT_AS } from "./identifier";
5
-
6
- test("An IdentifierTransform adds identifiers correctly", () => {
7
- const data = range(BLOCK_SIZE * 2).map((x) => ({ data: x }));
8
-
9
- const identifiedData = processData(
10
- new IdentifierTransform({ type: "identifier" }),
11
- data
12
- );
13
-
14
- // The fist block is skipped
15
- const firstId = BLOCK_SIZE;
16
-
17
- expect(identifiedData[0]).toEqual({ data: 0, [DEFAULT_AS]: firstId });
18
- expect(identifiedData[1]).toEqual({ data: 1, [DEFAULT_AS]: firstId + 1 });
19
- expect(identifiedData[BLOCK_SIZE]).toEqual({
20
- data: BLOCK_SIZE,
21
- [DEFAULT_AS]: firstId + BLOCK_SIZE,
22
- });
23
- expect(identifiedData[BLOCK_SIZE + 1]).toEqual({
24
- data: BLOCK_SIZE + 1,
25
- [DEFAULT_AS]: firstId + BLOCK_SIZE + 1,
26
- });
27
- });
28
-
29
- test("Another transform instance adds identifiers correctly", () => {
30
- const data = range(BLOCK_SIZE * 2).map((x) => ({ data: x }));
31
- // Another instance
32
- const identifiedData = processData(
33
- new IdentifierTransform({ type: "identifier" }),
34
- data
35
- );
36
-
37
- // The fist block was skipped and the previous test case consumed two blocks
38
- const firstId = BLOCK_SIZE * 3;
39
-
40
- expect(identifiedData[0]).toEqual({ data: 0, [DEFAULT_AS]: firstId });
41
- expect(identifiedData[1]).toEqual({ data: 1, [DEFAULT_AS]: firstId + 1 });
42
- expect(identifiedData[BLOCK_SIZE]).toEqual({
43
- data: BLOCK_SIZE,
44
- [DEFAULT_AS]: firstId + BLOCK_SIZE,
45
- });
46
- expect(identifiedData[BLOCK_SIZE + 1]).toEqual({
47
- data: BLOCK_SIZE + 1,
48
- [DEFAULT_AS]: firstId + BLOCK_SIZE + 1,
49
- });
50
- });
51
-
52
- test("IdentifierTransform recycles allocated blocks", () => {
53
- let data = range(BLOCK_SIZE * 2).map((x) => ({ data: x }));
54
-
55
- const transform = new IdentifierTransform({ type: "identifier" });
56
- let identifiedData = processData(transform, data);
57
-
58
- let firstId = BLOCK_SIZE * 5;
59
-
60
- expect(identifiedData[0]).toEqual({ data: 0, [DEFAULT_AS]: firstId });
61
- expect(identifiedData[BLOCK_SIZE]).toEqual({
62
- data: BLOCK_SIZE,
63
- [DEFAULT_AS]: firstId + BLOCK_SIZE,
64
- });
65
-
66
- data = range(BLOCK_SIZE * 3).map((x) => ({ data: x }));
67
-
68
- // Resetting the transform. It should now reuse the allocated blocks.
69
- transform.reset();
70
- identifiedData = processData(transform, data);
71
-
72
- expect(identifiedData[0]).toEqual({ data: 0, [DEFAULT_AS]: firstId });
73
- expect(identifiedData[BLOCK_SIZE]).toEqual({
74
- data: BLOCK_SIZE,
75
- [DEFAULT_AS]: firstId + BLOCK_SIZE,
76
- });
77
-
78
- // ... and reserve one extra
79
- expect(identifiedData[BLOCK_SIZE * 2]).toEqual({
80
- data: BLOCK_SIZE * 2,
81
- [DEFAULT_AS]: firstId + BLOCK_SIZE * 2,
82
- });
83
- });
@@ -1,101 +0,0 @@
1
- import { asArray } from "../../utils/arrayUtils";
2
- import { field } from "../../utils/field";
3
- import FlowNode, { BEHAVIOR_MODIFIES } from "../flowNode";
4
-
5
- /**
6
- * @typedef {import("../../spec/transform").LinearizeGenomicCoordinateParams} LinearizeGenomicCoordinateParams
7
- * @typedef {import("../../view/view").default} View
8
- */
9
- export default class LinearizeGenomicCoordinate extends FlowNode {
10
- get behavior() {
11
- return BEHAVIOR_MODIFIES;
12
- }
13
-
14
- /**
15
- *
16
- * @param {LinearizeGenomicCoordinateParams} params
17
- * @param {View} view
18
- */
19
- constructor(params, view) {
20
- super();
21
-
22
- const channel = params.channel ?? "x";
23
-
24
- if (!["x", "y"].includes(channel)) {
25
- throw new Error("Invalid channel: " + channel);
26
- }
27
-
28
- const genome = view.getScaleResolution(channel).getGenome();
29
- if (!genome) {
30
- throw new Error(
31
- "LinearizeGenomicCoordinate transform requires a locus scale!"
32
- );
33
- }
34
-
35
- const chromAccessor = field(params.chrom);
36
- const posAccessors = asArray(params.pos).map((pos) => field(pos));
37
- const as = asArray(params.as);
38
-
39
- if (posAccessors.length != as.length) {
40
- throw new Error(
41
- 'The number of "pos" and "as" elements must be equal!'
42
- );
43
- }
44
-
45
- const offsetParam = asArray(params.offset);
46
-
47
- /** @type {number[]} */
48
- let posOffsets;
49
-
50
- if (offsetParam.length == 0) {
51
- posOffsets = new Array(posAccessors.length).fill(0);
52
- } else if (offsetParam.length == 1) {
53
- posOffsets = new Array(posAccessors.length).fill(offsetParam[0]);
54
- } else if (offsetParam.length == posAccessors.length) {
55
- posOffsets = offsetParam;
56
- } else {
57
- throw new Error(
58
- `Invalid "offset" parameter: ${JSON.stringify(params.offset)}!`
59
- );
60
- }
61
-
62
- const setter = new Function(
63
- "datum",
64
- "chromOffset",
65
- "posAccessors",
66
- as
67
- .map(
68
- (a, i) =>
69
- `datum[${JSON.stringify(
70
- a
71
- )}] = chromOffset + +posAccessors[${i}](datum) - ${
72
- posOffsets[i]
73
- };`
74
- )
75
- .join("\n")
76
- );
77
-
78
- /** @type {any} */
79
- let lastChrom;
80
- let chromOffset = 0;
81
-
82
- /** @param {string | number} chrom */
83
- const getChromOffset = (chrom) => {
84
- if (chrom !== lastChrom) {
85
- chromOffset = genome.cumulativeChromPositions.get(chrom);
86
- if (chromOffset === undefined) {
87
- throw new Error("Unknown chromosome/contig: " + chrom);
88
- }
89
- lastChrom = chrom;
90
- }
91
-
92
- return chromOffset;
93
- };
94
-
95
- /** @param {Record<string, any>} datum */
96
- this.handle = (datum) => {
97
- setter(datum, getChromOffset(chromAccessor(datum)), posAccessors);
98
- this._propagate(datum);
99
- };
100
- }
101
- }
@@ -1,44 +0,0 @@
1
- import FlowNode, { BEHAVIOR_MODIFIES } from "../flowNode";
2
- import fontMetadata from "../../fonts/Lato-Regular.json";
3
- import getMetrics from "../../fonts/bmFontMetrics";
4
- import { field } from "../../utils/field";
5
-
6
- /**
7
- * Measures text length. This is mainly intended for reading-direction arrows
8
- * in gene annotations.
9
- *
10
- * @typedef {import("../../spec/transform").MeasureTextParams} MeasureTextParams
11
- */
12
- export default class MeasureTextTransform extends FlowNode {
13
- get behavior() {
14
- return BEHAVIOR_MODIFIES;
15
- }
16
-
17
- /**
18
- *
19
- * @param {MeasureTextParams} config
20
- */
21
- constructor(config) {
22
- super();
23
-
24
- const metrics = getMetrics(fontMetadata);
25
- const accessor = field(config.field);
26
- const as = config.as;
27
- // TODO: Support custom fonts.
28
- const size = config.fontSize;
29
-
30
- /**
31
- *
32
- * @param {any} datum
33
- */
34
- this.handle = (datum) => {
35
- const text = accessor(datum);
36
- if (text !== undefined) {
37
- datum[as] = metrics.measureWidth(text, size);
38
- } else {
39
- datum[as] = 0;
40
- }
41
- this._propagate(datum);
42
- };
43
- }
44
- }