@genome-spy/core 0.30.0 → 0.30.3

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 +16379 -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,367 +0,0 @@
1
- import Collector from "../data/collector";
2
- import createTransform from "../data/transforms/transformFactory";
3
- import createDataSource from "../data/sources/dataSourceFactory";
4
- import UnitView from "./unitView";
5
- import { BEHAVIOR_MODIFIES } from "../data/flowNode";
6
- import CloneTransform from "../data/transforms/clone";
7
- import { isDynamicCallbackData } from "../data/sources/dynamicCallbackSource";
8
- import DataFlow from "../data/dataFlow";
9
- import DataSource from "../data/sources/dataSource";
10
- import {
11
- isChannelDefWithScale,
12
- isChromPosDef,
13
- isDatumDef,
14
- isFieldDef,
15
- isPositionalChannel,
16
- getPrimaryChannel,
17
- } from "../encoder/encoder";
18
- import LinearizeGenomicCoordinate from "../data/transforms/linearizeGenomicCoordinate";
19
- import { isAggregateSamplesSpec } from "./viewFactory";
20
- import { group } from "d3-array";
21
- import IdentifierTransform from "../data/transforms/identifier";
22
- import { invalidate } from "../utils/propertyCacher";
23
- import NamedSource, { isNamedData } from "../data/sources/namedSource";
24
-
25
- /**
26
- * @typedef {import("./view").default} View
27
- * @typedef {import("../data/flowNode").default} FlowNode
28
- * @typedef {import("../spec/channel").Channel} Channel
29
- * @typedef {import("../spec/channel").Encoding} Encoding
30
- *
31
- * @param {View} root
32
- * @param {DataFlow<View>} [existingFlow] Add data flow
33
- * graphs to an existing DataFlow object.
34
- */
35
- export function buildDataFlow(root, existingFlow) {
36
- /** @type {FlowNode[]} "Current nodes" on the path from view root to the current view */
37
- const nodeStack = [];
38
-
39
- /** @type {FlowNode} */
40
- let currentNode;
41
-
42
- /** @type {DataFlow<View>} */
43
- const dataFlow = existingFlow ?? new DataFlow();
44
-
45
- /** @type {(function():void)[]} */
46
- const postProcessOps = [];
47
-
48
- /**
49
- * @param {FlowNode} node
50
- * @param {function():Error} [onMissingParent]
51
- * @returns {FlowNode} The appended node
52
- */
53
- function appendNode(node, onMissingParent = () => undefined) {
54
- if (!currentNode) {
55
- throw (
56
- onMissingParent() ||
57
- new Error("Cannot append data flow node, no parent exist!")
58
- );
59
- }
60
- currentNode.addChild(node);
61
- currentNode = node;
62
- return node;
63
- }
64
-
65
- /**
66
- * @param {FlowNode} transform
67
- * @param {any} [params]
68
- * @returns {FlowNode} The appended node
69
- */
70
- function appendTransform(transform, params) {
71
- return appendNode(
72
- transform,
73
- () =>
74
- new Error(
75
- `Cannot append a transform because no (inherited) data are available! ${
76
- params ? JSON.stringify(params) : ""
77
- }`
78
- )
79
- );
80
- }
81
-
82
- /**
83
- *
84
- * @param {import("../spec/transform").TransformParams[]} transforms
85
- * @param {View} view
86
- */
87
- function createTransforms(transforms, view) {
88
- for (const params of transforms) {
89
- /** @type {FlowNode} */
90
- let transform;
91
- try {
92
- transform = createTransform(params, view);
93
- } catch (e) {
94
- console.warn(e);
95
- throw new Error(
96
- `Cannot initialize "${params.type}" transform: ${e}`
97
- );
98
- }
99
-
100
- if (transform.behavior & BEHAVIOR_MODIFIES) {
101
- // Make defensive copies before every modifying transform to
102
- // ensure that modifications don't inadvertently become visible
103
- // in other branches of the flow.
104
- // These can be later optimized away where possible.
105
- appendTransform(new CloneTransform());
106
- }
107
- appendTransform(transform);
108
- }
109
- }
110
-
111
- /** @param {View} view */
112
- const processView = (view) => {
113
- nodeStack.push(currentNode);
114
-
115
- if (view.spec.data) {
116
- const dataSource = isDynamicCallbackData(view.spec.data)
117
- ? view.getDynamicDataSource()
118
- : isNamedData(view.spec.data)
119
- ? // TODO: Only one NamedSource instance per unique name should exists
120
- new NamedSource(
121
- view.spec.data,
122
- view.context.getNamedDataFromProvider
123
- )
124
- : createDataSource(view.spec.data, view.getBaseUrl());
125
-
126
- currentNode = dataSource;
127
- dataFlow.addDataSource(dataSource, view);
128
- }
129
-
130
- if (view.spec.transform) {
131
- createTransforms(view.spec.transform, view);
132
- }
133
-
134
- if (view instanceof UnitView) {
135
- if (!currentNode) {
136
- throw new Error("A unit view has no (inherited) data source");
137
- }
138
-
139
- // Support chrom/pos channelDefs
140
- const linearize = linearizeLocusAccess(view);
141
- if (linearize) {
142
- postProcessOps.push(linearize.rewrite);
143
- for (const transform of linearize.transforms) {
144
- // TODO: Transforms should not be added if they already exist in the flow.
145
- // Alternatively they should be optimized away.
146
- // TODO: Add CloneTransform
147
- appendTransform(transform);
148
- }
149
- }
150
-
151
- if (view.mark.isPickingParticipant()) {
152
- // TODO: Add CloneTransform
153
- appendTransform(
154
- new IdentifierTransform({ type: "identifier" })
155
- );
156
- }
157
-
158
- const collector = new Collector({
159
- type: "collect",
160
- groupby: view.getFacetFields(),
161
- sort: getCompareParamsForView(
162
- view,
163
- linearize?.rewrittenEncoding
164
- ),
165
- });
166
-
167
- appendNode(collector);
168
- dataFlow.addCollector(collector, view);
169
- }
170
-
171
- if (isAggregateSamplesSpec(view.spec)) {
172
- // TODO: implement summarization of layer views
173
- }
174
- };
175
-
176
- /** @param {View} view */
177
- processView.postOrder = (view) => {
178
- currentNode = nodeStack.pop();
179
- };
180
-
181
- root.visit(processView);
182
-
183
- postProcessOps.forEach((op) => op());
184
-
185
- return dataFlow;
186
- }
187
-
188
- /**
189
- * Changes the ChromPos channelDefs into FieldDefs and returns
190
- * LinearizeGenomicCoordinate transform(s) that should be inserted into
191
- * the data flow.
192
- *
193
- * @param {View} view
194
- */
195
- export function linearizeLocusAccess(view) {
196
- /** @type {FlowNode[]} */
197
- const transforms = [];
198
-
199
- /** @type {Encoding} */
200
- const rewrittenEncoding = {};
201
-
202
- /** @type {{ channel: Channel, chromPosDef: import("../spec/channel").ChromPosDef}[]} */
203
- const channelsAndChromPosDefs = [];
204
-
205
- // Optimize the number of transforms. Use only a single transform for positions
206
- // that share the chromosome field and channel.
207
- for (const [c, channelDef] of Object.entries(view.getEncoding())) {
208
- const channel = /** @type {Channel} */ (c);
209
- if (isPositionalChannel(channel) && isChromPosDef(channelDef)) {
210
- channelsAndChromPosDefs.push({ channel, chromPosDef: channelDef });
211
- }
212
- }
213
-
214
- // Nngh. group uses InternMap but doesn't have a way to define an interning function.
215
- // Have to use multi-level grouping.
216
- const grouped = group(
217
- channelsAndChromPosDefs,
218
- (d) => /** @type {"x" | "y"} */ (getPrimaryChannel(d.channel)),
219
- (d) => d.chromPosDef.chrom
220
- );
221
-
222
- for (const [primaryChan, chromAndStuff] of grouped.entries()) {
223
- for (const [chrom, chanChromPos] of chromAndStuff.entries()) {
224
- /** @type {string[]} */
225
- const pos = [];
226
- /** @type {string[]} */
227
- const as = [];
228
- /** @type {number[]} */
229
- const offset = [];
230
-
231
- for (const { channel, chromPosDef } of chanChromPos) {
232
- /** @param {string} str */
233
- const strip = (str) => str.replace(/[^A-Za-z0-9_]/g, "");
234
- const linearizedField = [
235
- "_linearized_",
236
- strip(chromPosDef.chrom),
237
- "_",
238
- strip(chromPosDef.pos),
239
- ].join("");
240
-
241
- // Prefer using the spec directly because getEncoding() returns inherited props too.
242
- // TODO: I think this is not robust enough. Needs more work...
243
- /** @type {any} */
244
- const newFieldDef = {
245
- ...(view.spec.encoding?.[channel] ??
246
- view.getEncoding()[channel] ??
247
- {}),
248
- field: linearizedField,
249
- };
250
- delete newFieldDef.chrom;
251
- delete newFieldDef.pos;
252
- if (!newFieldDef.type && chromPosDef.type) {
253
- newFieldDef.type = chromPosDef.type;
254
- }
255
-
256
- rewrittenEncoding[channel] = newFieldDef;
257
-
258
- pos.push(chromPosDef.pos);
259
- offset.push(chromPosDef.offset ?? 0);
260
- as.push(linearizedField);
261
- }
262
-
263
- transforms.push(
264
- new LinearizeGenomicCoordinate(
265
- {
266
- type: "linearizeGenomicCoordinate",
267
- channel: primaryChan,
268
- chrom: chrom,
269
- pos,
270
- offset,
271
- as,
272
- },
273
- view
274
- )
275
- );
276
- }
277
- }
278
-
279
- return transforms.length
280
- ? {
281
- transforms,
282
- rewrittenEncoding,
283
- /**
284
- * Should be called after the whole flow has been created in order to
285
- * not disrupt inheritance of encodings
286
- */
287
- rewrite: () => {
288
- view.spec.encoding = {
289
- ...view.spec.encoding,
290
- ...rewrittenEncoding,
291
- };
292
- // This is so ugly...
293
- // @ts-ignore
294
- invalidate(view.mark, "encoding");
295
- },
296
- }
297
- : undefined;
298
- }
299
-
300
- /**
301
- * @param {View} view
302
- * @param {Encoding} [encoding]
303
- * @returns {import("../spec/transform").CompareParams}
304
- */
305
- function getCompareParamsForView(view, encoding) {
306
- // TODO: Should sort by min(x, x2).
307
- const e = { ...view.getEncoding(), ...encoding }.x;
308
- if (isChannelDefWithScale(e)) {
309
- if (view.getScaleResolution("x")?.isZoomable()) {
310
- if (isFieldDef(e)) {
311
- return { field: e.field };
312
- } else if (isDatumDef(e)) {
313
- // Nop
314
- } else {
315
- // TODO: Support expr by inserting a Formula transform
316
- throw new Error(
317
- "A zoomable x channel must be mapped to a field."
318
- );
319
- }
320
- }
321
- }
322
- }
323
-
324
- /**
325
- * A helper function for creating linear data flows programmatically.
326
- *
327
- * @param {H} dataSource A data source or any other initial FlowNode.
328
- * @param {...FlowNode} transforms
329
- * @template {FlowNode} H
330
- */
331
- export function createChain(dataSource, ...transforms) {
332
- /** @type {FlowNode} */
333
- let node = dataSource;
334
- for (const transform of transforms) {
335
- node.addChild(transform);
336
- node = transform;
337
- }
338
-
339
- /** @type {Collector} */
340
- let collector;
341
-
342
- if (node instanceof Collector) {
343
- collector = node;
344
- } else {
345
- collector = new Collector();
346
- node.addChild(collector);
347
- }
348
-
349
- /** @type {function():Promise<Iterable<import("../data/flowNode").Datum>>} */
350
- let loadAndCollect;
351
- if (dataSource instanceof DataSource) {
352
- loadAndCollect = async () => {
353
- await dataSource.load();
354
- return collector.getData();
355
- };
356
- } else {
357
- loadAndCollect = async () => {
358
- throw new Error("The root node is not derived from DataSource!");
359
- };
360
- }
361
-
362
- return {
363
- dataSource,
364
- collector,
365
- loadAndCollect,
366
- };
367
- }
@@ -1,125 +0,0 @@
1
- import { expect, test } from "vitest";
2
- import Collector from "../data/collector";
3
- import FlowNode from "../data/flowNode";
4
- import FilterTransform from "../data/transforms/filter";
5
- import FormulaTransform from "../data/transforms/formula";
6
- import InlineSource from "../data/sources/inlineSource";
7
- import SequenceSource from "../data/sources/sequenceSource";
8
- import { buildDataFlow } from "./flowBuilder";
9
- import { create } from "./testUtils";
10
- import CloneTransform from "../data/transforms/clone";
11
- import LayerView from "./layerView";
12
- import UnitView from "./unitView";
13
-
14
- /**
15
- *
16
- * @param {FlowNode} root
17
- * @param {number[]} path
18
- */
19
- function byPath(root, path) {
20
- for (const elem of path) {
21
- root = root.children[elem];
22
- }
23
- return root;
24
- }
25
-
26
- /** @type {import("../spec/mark").MarkConfigAndType} */
27
- const mark = {
28
- type: "rect",
29
- tooltip: null,
30
- };
31
-
32
- test("Trivial flow", () => {
33
- const root = create(
34
- {
35
- data: { values: [3.141] },
36
- transform: [
37
- {
38
- type: "formula",
39
- expr: "datum.data * 2",
40
- as: "x",
41
- },
42
- ],
43
- mark,
44
- },
45
- UnitView
46
- );
47
-
48
- const flow = buildDataFlow(root);
49
- const dataSource = flow.dataSources[0];
50
-
51
- expect(dataSource).toBeInstanceOf(InlineSource);
52
- expect(byPath(dataSource, [0])).toBeInstanceOf(CloneTransform);
53
- expect(byPath(dataSource, [0, 0])).toBeInstanceOf(FormulaTransform);
54
- expect(byPath(dataSource, [0, 0, 0])).toBeInstanceOf(Collector);
55
-
56
- expect(flow.collectors[0]).toBe(byPath(dataSource, [0, 0, 0]));
57
- });
58
-
59
- test("Branching flow", () => {
60
- const root = create(
61
- {
62
- data: { values: [3.141] },
63
- layer: [
64
- {
65
- transform: [
66
- {
67
- type: "formula",
68
- expr: "datum.data * 2",
69
- as: "x",
70
- },
71
- ],
72
- mark,
73
- },
74
- {
75
- transform: [
76
- {
77
- type: "filter",
78
- expr: "datum.data > 4",
79
- },
80
- ],
81
- mark,
82
- },
83
- ],
84
- },
85
- LayerView
86
- );
87
-
88
- const dataSource = buildDataFlow(root).dataSources[0];
89
-
90
- expect(dataSource).toBeInstanceOf(InlineSource);
91
- // Formula transform modifies data and it should be implicitly preceded by CloneTransform
92
- expect(byPath(dataSource, [0])).toBeInstanceOf(CloneTransform);
93
- expect(byPath(dataSource, [0, 0])).toBeInstanceOf(FormulaTransform);
94
- expect(byPath(dataSource, [0, 0, 0])).toBeInstanceOf(Collector);
95
- expect(byPath(dataSource, [1])).toBeInstanceOf(FilterTransform);
96
- expect(byPath(dataSource, [1, 0])).toBeInstanceOf(Collector);
97
- });
98
-
99
- test("Nested data sources", () => {
100
- const root = create(
101
- {
102
- data: { values: [1] },
103
- transform: [{ type: "filter", expr: "datum.data > 0" }],
104
- layer: [
105
- {
106
- data: { sequence: { start: 0, stop: 5 } },
107
- transform: [{ type: "formula", expr: "3", as: "foo" }],
108
- mark,
109
- },
110
- ],
111
- },
112
- LayerView
113
- );
114
-
115
- const dataSources = buildDataFlow(root).dataSources;
116
-
117
- expect(dataSources[0]).toBeInstanceOf(InlineSource);
118
- expect(dataSources[0].children[0]).toBeInstanceOf(FilterTransform);
119
- expect(dataSources[0].children[0].children.length).toEqual(0);
120
-
121
- expect(byPath(dataSources[1], [])).toBeInstanceOf(SequenceSource);
122
- expect(byPath(dataSources[1], [0])).toBeInstanceOf(CloneTransform);
123
- expect(byPath(dataSources[1], [0, 0])).toBeInstanceOf(FormulaTransform);
124
- expect(byPath(dataSources[1], [0, 0, 0])).toBeInstanceOf(Collector);
125
- });