@genome-spy/core 0.28.3 → 0.30.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.
- package/dist/index.js +32 -32
- package/dist/schema.json +77 -10
- package/package.json +2 -2
- package/src/genomeSpy.js +1 -0
- package/src/gl/webGLHelper.js +39 -24
- package/src/marks/mark.js +18 -2
- package/src/scale/glslScaleGenerator.js +25 -11
- package/src/spec/sampleView.d.ts +180 -0
- package/src/spec/transform.d.ts +2 -2
- package/src/spec/view.d.ts +1 -23
- package/src/tooltip/dataTooltipHandler.js +16 -12
- package/src/view/gridView.js +6 -2
- package/src/view/scaleResolution.js +6 -0
- package/src/view/viewUtils.js +1 -1
- package/src/view/zoom.js +2 -2
package/dist/schema.json
CHANGED
|
@@ -3325,7 +3325,8 @@
|
|
|
3325
3325
|
"type": "object"
|
|
3326
3326
|
},
|
|
3327
3327
|
"samples": {
|
|
3328
|
-
"$ref": "#/definitions/SampleDef"
|
|
3328
|
+
"$ref": "#/definitions/SampleDef",
|
|
3329
|
+
"description": "Sample metadata definition. If the object is empty, the sample identifiers will be inferred from the data."
|
|
3329
3330
|
},
|
|
3330
3331
|
"spec": {
|
|
3331
3332
|
"anyOf": [
|
|
@@ -3335,7 +3336,8 @@
|
|
|
3335
3336
|
{
|
|
3336
3337
|
"$ref": "#/definitions/UnitSpec"
|
|
3337
3338
|
}
|
|
3338
|
-
]
|
|
3339
|
+
],
|
|
3340
|
+
"description": "The view specification to be repeated for each sample."
|
|
3339
3341
|
},
|
|
3340
3342
|
"stickySummaries": {
|
|
3341
3343
|
"type": "boolean"
|
|
@@ -3871,19 +3873,23 @@
|
|
|
3871
3873
|
"additionalProperties": false,
|
|
3872
3874
|
"properties": {
|
|
3873
3875
|
"barScale": {
|
|
3874
|
-
"$ref": "#/definitions/Scale"
|
|
3876
|
+
"$ref": "#/definitions/Scale",
|
|
3877
|
+
"description": "An optional scale definition for mapping the attribute to the width of a metadata rectangle."
|
|
3875
3878
|
},
|
|
3876
3879
|
"scale": {
|
|
3877
3880
|
"$ref": "#/definitions/Scale",
|
|
3878
|
-
"description": "
|
|
3881
|
+
"description": "Scale definition for the (default) color channel"
|
|
3879
3882
|
},
|
|
3880
3883
|
"type": {
|
|
3881
|
-
"$ref": "#/definitions/Type"
|
|
3884
|
+
"$ref": "#/definitions/Type",
|
|
3885
|
+
"description": "The attribute type. One of `\"nominal\"`, `\"ordinal\"`, or `\"quantitative\"`."
|
|
3882
3886
|
},
|
|
3883
3887
|
"visible": {
|
|
3888
|
+
"description": "Whether the attribute is visible by default.",
|
|
3884
3889
|
"type": "boolean"
|
|
3885
3890
|
},
|
|
3886
3891
|
"width": {
|
|
3892
|
+
"description": "Width of the column in pixels.",
|
|
3887
3893
|
"type": "number"
|
|
3888
3894
|
}
|
|
3889
3895
|
},
|
|
@@ -3895,14 +3901,72 @@
|
|
|
3895
3901
|
"SampleDef": {
|
|
3896
3902
|
"additionalProperties": false,
|
|
3897
3903
|
"properties": {
|
|
3904
|
+
"attributeLabelAngle": {
|
|
3905
|
+
"description": "Angle to be added to the default label angle (-90).\n\n**Default value:** `0`",
|
|
3906
|
+
"type": "number"
|
|
3907
|
+
},
|
|
3908
|
+
"attributeLabelFont": {
|
|
3909
|
+
"description": "The font typeface. GenomeSpy uses [SDF](https://github.com/Chlumsky/msdfgen) versions of [Google Fonts](https://fonts.google.com/). Check their availability at the [A-Frame Fonts](https://github.com/etiennepinchon/aframe-fonts/tree/master/fonts) repository. System fonts are **not** supported.\n\n**Default value:** `\"Lato\"`",
|
|
3910
|
+
"type": "string"
|
|
3911
|
+
},
|
|
3912
|
+
"attributeLabelFontSize": {
|
|
3913
|
+
"description": "The font size in pixels.\n\n**Default value:** `11`",
|
|
3914
|
+
"type": "number"
|
|
3915
|
+
},
|
|
3916
|
+
"attributeLabelFontStyle": {
|
|
3917
|
+
"$ref": "#/definitions/FontStyle",
|
|
3918
|
+
"description": "The font style. Valid values: `\"normal\"` and `\"italic\"`.\n\n**Default value:** `\"normal\"`"
|
|
3919
|
+
},
|
|
3920
|
+
"attributeLabelFontWeight": {
|
|
3921
|
+
"$ref": "#/definitions/FontWeight",
|
|
3922
|
+
"description": "The font weight. The following strings and numbers are valid values: `\"thin\"` (`100`), `\"light\"` (`300`), `\"regular\"` (`400`), `\"normal\"` (`400`), `\"medium\"` (`500`), `\"bold\"` (`700`), `\"black\"` (`900`)\n\n**Default value:** `\"regular\"`"
|
|
3923
|
+
},
|
|
3924
|
+
"attributeSize": {
|
|
3925
|
+
"description": "Default size (width) of the metadata attribute columns. Can be configured per attribute using the `attributes` property.\n\n**Default value:** `10`",
|
|
3926
|
+
"type": "number"
|
|
3927
|
+
},
|
|
3928
|
+
"attributeSpacing": {
|
|
3929
|
+
"description": "Spacing between attribute columns in pixels.\n\n**Default value:** `1`",
|
|
3930
|
+
"type": "number"
|
|
3931
|
+
},
|
|
3898
3932
|
"attributes": {
|
|
3899
3933
|
"additionalProperties": {
|
|
3900
3934
|
"$ref": "#/definitions/SampleAttributeDef"
|
|
3901
3935
|
},
|
|
3936
|
+
"description": "Explicitly specify the sample attributes.",
|
|
3902
3937
|
"type": "object"
|
|
3903
3938
|
},
|
|
3904
3939
|
"data": {
|
|
3905
|
-
"$ref": "#/definitions/Data"
|
|
3940
|
+
"$ref": "#/definitions/Data",
|
|
3941
|
+
"description": "Optional metadata about the samples."
|
|
3942
|
+
},
|
|
3943
|
+
"labelAlign": {
|
|
3944
|
+
"$ref": "#/definitions/Align",
|
|
3945
|
+
"description": "The horizontal alignment of the text. One of `\"left\"`, `\"center\"`, or `\"right\"`.\n\n**Default value:** `\"left\"`"
|
|
3946
|
+
},
|
|
3947
|
+
"labelFont": {
|
|
3948
|
+
"description": "The font typeface. GenomeSpy uses [SDF](https://github.com/Chlumsky/msdfgen) versions of [Google Fonts](https://fonts.google.com/). Check their availability at the [A-Frame Fonts](https://github.com/etiennepinchon/aframe-fonts/tree/master/fonts) repository. System fonts are **not** supported.\n\n**Default value:** `\"Lato\"`",
|
|
3949
|
+
"type": "string"
|
|
3950
|
+
},
|
|
3951
|
+
"labelFontSize": {
|
|
3952
|
+
"description": "The font size in pixels.\n\n**Default value:** `11`",
|
|
3953
|
+
"type": "number"
|
|
3954
|
+
},
|
|
3955
|
+
"labelFontStyle": {
|
|
3956
|
+
"$ref": "#/definitions/FontStyle",
|
|
3957
|
+
"description": "The font style. Valid values: `\"normal\"` and `\"italic\"`.\n\n**Default value:** `\"normal\"`"
|
|
3958
|
+
},
|
|
3959
|
+
"labelFontWeight": {
|
|
3960
|
+
"$ref": "#/definitions/FontWeight",
|
|
3961
|
+
"description": "The font weight. The following strings and numbers are valid values: `\"thin\"` (`100`), `\"light\"` (`300`), `\"regular\"` (`400`), `\"normal\"` (`400`), `\"medium\"` (`500`), `\"bold\"` (`700`), `\"black\"` (`900`)\n\n**Default value:** `\"regular\"`"
|
|
3962
|
+
},
|
|
3963
|
+
"labelLength": {
|
|
3964
|
+
"description": "How much space in pixels to reserve for the labels.\n\n**Default:** `140`",
|
|
3965
|
+
"type": "number"
|
|
3966
|
+
},
|
|
3967
|
+
"labelTitleText": {
|
|
3968
|
+
"description": "Text in the label title\n\n**Default:** `\"Sample name\"`",
|
|
3969
|
+
"type": "string"
|
|
3906
3970
|
}
|
|
3907
3971
|
},
|
|
3908
3972
|
"type": "object"
|
|
@@ -3927,6 +3991,7 @@
|
|
|
3927
3991
|
},
|
|
3928
3992
|
"SampleSpec": {
|
|
3929
3993
|
"additionalProperties": false,
|
|
3994
|
+
"description": "A view specification for a SampleView. This is only functional in the GenomeSpy app.",
|
|
3930
3995
|
"properties": {
|
|
3931
3996
|
"baseUrl": {
|
|
3932
3997
|
"type": "string"
|
|
@@ -4012,7 +4077,8 @@
|
|
|
4012
4077
|
"type": "object"
|
|
4013
4078
|
},
|
|
4014
4079
|
"samples": {
|
|
4015
|
-
"$ref": "#/definitions/SampleDef"
|
|
4080
|
+
"$ref": "#/definitions/SampleDef",
|
|
4081
|
+
"description": "Sample metadata definition. If the object is empty, the sample identifiers will be inferred from the data."
|
|
4016
4082
|
},
|
|
4017
4083
|
"spec": {
|
|
4018
4084
|
"anyOf": [
|
|
@@ -4022,7 +4088,8 @@
|
|
|
4022
4088
|
{
|
|
4023
4089
|
"$ref": "#/definitions/UnitSpec"
|
|
4024
4090
|
}
|
|
4025
|
-
]
|
|
4091
|
+
],
|
|
4092
|
+
"description": "The view specification to be repeated for each sample."
|
|
4026
4093
|
},
|
|
4027
4094
|
"stickySummaries": {
|
|
4028
4095
|
"type": "boolean"
|
|
@@ -4478,10 +4545,10 @@
|
|
|
4478
4545
|
},
|
|
4479
4546
|
"baseField": {
|
|
4480
4547
|
"$ref": "#/definitions/Field",
|
|
4481
|
-
"description": "The field that contains the base or amino acid. Used for information content calculation when the offset is `\"information\"`. The data
|
|
4548
|
+
"description": "The field that contains the base or amino acid. Used for information content calculation when the offset is `\"information\"`. The data objects that have `null` in the baseField are considered gaps and they are taken into account when scaling the the locus' information content."
|
|
4482
4549
|
},
|
|
4483
4550
|
"cardinality": {
|
|
4484
|
-
"description": "Cardinality, e.g., the number if distinct bases or amino acids. Used for information content calculation when the offset is `\"information\"`.\n\n**Default:** `4
|
|
4551
|
+
"description": "Cardinality, e.g., the number if distinct bases or amino acids. Used for information content calculation when the offset is `\"information\"`.\n\n**Default:** `4`",
|
|
4485
4552
|
"type": "number"
|
|
4486
4553
|
},
|
|
4487
4554
|
"field": {
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"contributors": [],
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.30.0",
|
|
11
11
|
"main": "dist/index.js",
|
|
12
12
|
"module": "src/index.js",
|
|
13
13
|
"exports": {
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"vega-scale": "^7.1.1",
|
|
54
54
|
"vega-util": "^1.16.0"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "c8fe26f3421a1bec7323428f0bd7da46cda34dba"
|
|
57
57
|
}
|
package/src/genomeSpy.js
CHANGED
|
@@ -378,6 +378,7 @@ export default class GenomeSpy {
|
|
|
378
378
|
// Now that all data have been loaded, the domains may need adjusting
|
|
379
379
|
this.viewRoot.visit((view) => {
|
|
380
380
|
for (const resolution of Object.values(view.resolutions.scale)) {
|
|
381
|
+
// TODO: Don't reconfigure multiple times
|
|
381
382
|
// IMPORTANT TODO: Check that discrete domains and indexers match!!!!!!!!!
|
|
382
383
|
resolution.reconfigure();
|
|
383
384
|
}
|
package/src/gl/webGLHelper.js
CHANGED
|
@@ -9,7 +9,12 @@ import {
|
|
|
9
9
|
} from "twgl.js";
|
|
10
10
|
import { isArray, isString } from "vega-util";
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
isContinuous,
|
|
14
|
+
isDiscrete,
|
|
15
|
+
isDiscretizing,
|
|
16
|
+
isInterpolating,
|
|
17
|
+
} from "vega-scale";
|
|
13
18
|
import {
|
|
14
19
|
createDiscreteColorTexture,
|
|
15
20
|
createDiscreteTexture,
|
|
@@ -321,43 +326,53 @@ export default class WebGLHelper {
|
|
|
321
326
|
const props = resolution.getScaleProps();
|
|
322
327
|
|
|
323
328
|
const scale = resolution.getScale();
|
|
329
|
+
const range = /** @type {any[]} */ (scale.range());
|
|
324
330
|
|
|
325
331
|
/** @type {WebGLTexture} */
|
|
326
332
|
let texture;
|
|
327
333
|
|
|
328
334
|
if (props.scheme) {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
count = fixCount(count, scale);
|
|
334
|
-
|
|
335
|
-
texture = createSchemeTexture(
|
|
336
|
-
props.scheme,
|
|
337
|
-
this.gl,
|
|
338
|
-
count,
|
|
339
|
-
existingTexture
|
|
340
|
-
);
|
|
341
|
-
} else {
|
|
342
|
-
// No scheme, assume that colors are specified in the range
|
|
343
|
-
|
|
344
|
-
const range = /** @type {any[]} */ (scale.range());
|
|
345
|
-
|
|
346
|
-
if (isInterpolating(scale.type)) {
|
|
347
|
-
texture = createInterpolatedColorTexture(
|
|
335
|
+
if (scale.type == "threshold" && range) {
|
|
336
|
+
// Scale initialization may have configured the range. Let's use it.
|
|
337
|
+
texture = createDiscreteColorTexture(
|
|
348
338
|
range,
|
|
349
|
-
props.interpolate,
|
|
350
339
|
this.gl,
|
|
340
|
+
scale.domain().length,
|
|
351
341
|
existingTexture
|
|
352
342
|
);
|
|
353
343
|
} else {
|
|
354
|
-
|
|
355
|
-
|
|
344
|
+
let count = isString(props.scheme)
|
|
345
|
+
? undefined
|
|
346
|
+
: props.scheme.count;
|
|
347
|
+
|
|
348
|
+
count = fixCount(count, scale);
|
|
349
|
+
|
|
350
|
+
texture = createSchemeTexture(
|
|
351
|
+
props.scheme,
|
|
356
352
|
this.gl,
|
|
357
|
-
|
|
353
|
+
count,
|
|
358
354
|
existingTexture
|
|
359
355
|
);
|
|
360
356
|
}
|
|
357
|
+
} else if (
|
|
358
|
+
// Interpolating
|
|
359
|
+
isInterpolating(scale.type) ||
|
|
360
|
+
// Or piecewise
|
|
361
|
+
(isContinuous(scale.type) && range.length > 2)
|
|
362
|
+
) {
|
|
363
|
+
texture = createInterpolatedColorTexture(
|
|
364
|
+
range,
|
|
365
|
+
props.interpolate,
|
|
366
|
+
this.gl,
|
|
367
|
+
existingTexture
|
|
368
|
+
);
|
|
369
|
+
} else {
|
|
370
|
+
texture = createDiscreteColorTexture(
|
|
371
|
+
range,
|
|
372
|
+
this.gl,
|
|
373
|
+
scale.domain().length,
|
|
374
|
+
existingTexture
|
|
375
|
+
);
|
|
361
376
|
}
|
|
362
377
|
|
|
363
378
|
this.rangeTextures.set(resolution, texture);
|
package/src/marks/mark.js
CHANGED
|
@@ -271,7 +271,16 @@ export default class Mark {
|
|
|
271
271
|
getSampleFacetMode() {
|
|
272
272
|
if (this.encoders.facetIndex) {
|
|
273
273
|
return SAMPLE_FACET_TEXTURE;
|
|
274
|
-
} else if (
|
|
274
|
+
} else if (
|
|
275
|
+
// If the UnitView is inside app's SampleView.
|
|
276
|
+
// TODO: This may break if non-faceted stuff is added to SampleView,
|
|
277
|
+
// e.g., view background or an x axis.
|
|
278
|
+
// This could also be more generic and work with other faceting views
|
|
279
|
+
// that will be available in the future.
|
|
280
|
+
[...this.unitView.getAncestors()].find(
|
|
281
|
+
(view) => "samples" in view.spec
|
|
282
|
+
)
|
|
283
|
+
) {
|
|
275
284
|
return SAMPLE_FACET_UNIFORM;
|
|
276
285
|
}
|
|
277
286
|
}
|
|
@@ -776,7 +785,14 @@ export default class Mark {
|
|
|
776
785
|
}
|
|
777
786
|
};
|
|
778
787
|
|
|
779
|
-
|
|
788
|
+
// If is either faceted or non-faceted, not both.
|
|
789
|
+
// An undefined key with vertices means that the mark is non-faceted.
|
|
790
|
+
// In such case, the same non-faceted data is repeated for each facet.
|
|
791
|
+
const facetId =
|
|
792
|
+
this.rangeMap.get(undefined).count == 0
|
|
793
|
+
? options.facetId
|
|
794
|
+
: undefined;
|
|
795
|
+
const rangeEntry = this.rangeMap.get(facetId);
|
|
780
796
|
|
|
781
797
|
return options.sampleFacetRenderingOptions
|
|
782
798
|
? function renderSampleFacetRange() {
|
|
@@ -314,7 +314,7 @@ export function generateScaleGlsl(channel, scale, channelDef) {
|
|
|
314
314
|
if (piecewise) {
|
|
315
315
|
// TODO: Handle range correctly. Now this assumes unit range.
|
|
316
316
|
scaleBody.push(
|
|
317
|
-
`transformed = (float(slot) + transformed) / (float(${name}.length()
|
|
317
|
+
`transformed = (float(slot) + transformed) / (float(${name}.length() - 1));`
|
|
318
318
|
);
|
|
319
319
|
}
|
|
320
320
|
} else {
|
|
@@ -463,26 +463,40 @@ export function isHighPrecisionScale(type) {
|
|
|
463
463
|
return type == "index" || type == "locus";
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
+
// Maximum precise index number is 2^(23 + 11) ~ 17G
|
|
467
|
+
// Higher number increases precision but makes zooming unstable
|
|
468
|
+
const BS = 2 ** 11;
|
|
469
|
+
const BM = BS - 1;
|
|
470
|
+
|
|
466
471
|
/**
|
|
467
|
-
* @param {number} x
|
|
472
|
+
* @param {number} x Must be an integer
|
|
468
473
|
* @param {number[]} [arr]
|
|
469
474
|
*/
|
|
470
|
-
export function splitHighPrecision(x, arr) {
|
|
471
|
-
//
|
|
472
|
-
//
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const hi = Math.round(x - lo);
|
|
477
|
-
arr ??= [];
|
|
475
|
+
export function splitHighPrecision(x, arr = []) {
|
|
476
|
+
// Using a bitmask is MUCH faster than using modulo (at least on Chrome 112)
|
|
477
|
+
// https://www.wikiwand.com/en/Modulo#Performance_issues
|
|
478
|
+
const lo = x & BM;
|
|
479
|
+
const hi = x - lo;
|
|
480
|
+
|
|
478
481
|
arr[0] = hi;
|
|
479
482
|
arr[1] = lo;
|
|
483
|
+
|
|
480
484
|
return arr;
|
|
481
485
|
}
|
|
482
486
|
|
|
487
|
+
/**
|
|
488
|
+
* @param {number} x
|
|
489
|
+
*/
|
|
490
|
+
function exactSplitHighPrecision(x) {
|
|
491
|
+
const lo = x % BS;
|
|
492
|
+
const hi = x - lo;
|
|
493
|
+
|
|
494
|
+
return [hi, lo];
|
|
495
|
+
}
|
|
496
|
+
|
|
483
497
|
/**
|
|
484
498
|
* @param {number[]} domain
|
|
485
499
|
*/
|
|
486
500
|
export function toHighPrecisionDomainUniform(domain) {
|
|
487
|
-
return [...
|
|
501
|
+
return [...exactSplitHighPrecision(domain[0]), domain[1] - domain[0]];
|
|
488
502
|
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { Type } from "./channel";
|
|
2
|
+
import { Data } from "./data";
|
|
3
|
+
import { Align, FontStyle, FontWeight } from "./font";
|
|
4
|
+
import { Scale } from "./scale";
|
|
5
|
+
import { LayerSpec, UnitSpec, ViewSpecBase } from "./view";
|
|
6
|
+
|
|
7
|
+
// TODO: Figure out how this could be moved to the app package and excluded
|
|
8
|
+
// from the core package.
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A view specification for a SampleView.
|
|
12
|
+
* This is only functional in the GenomeSpy app.
|
|
13
|
+
*/
|
|
14
|
+
export interface SampleSpec extends ViewSpecBase {
|
|
15
|
+
/**
|
|
16
|
+
* Sample metadata definition.
|
|
17
|
+
* If the object is empty, the sample identifiers will be inferred from the data.
|
|
18
|
+
*/
|
|
19
|
+
samples: SampleDef;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The view specification to be repeated for each sample.
|
|
23
|
+
*/
|
|
24
|
+
spec: LayerSpec | UnitSpec;
|
|
25
|
+
|
|
26
|
+
stickySummaries?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface SampleAttributeDef {
|
|
30
|
+
/**
|
|
31
|
+
* The attribute type. One of `"nominal"`, `"ordinal"`, or `"quantitative"`.
|
|
32
|
+
*/
|
|
33
|
+
type: Type; // TODO: Omit index/locus from available types
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Scale definition for the (default) color channel
|
|
37
|
+
*/
|
|
38
|
+
scale?: Scale;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* An optional scale definition for mapping the attribute to
|
|
42
|
+
* the width of a metadata rectangle.
|
|
43
|
+
*/
|
|
44
|
+
barScale?: Scale;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Width of the column in pixels.
|
|
48
|
+
*/
|
|
49
|
+
width?: number;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether the attribute is visible by default.
|
|
53
|
+
*/
|
|
54
|
+
visible?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface SampleDef {
|
|
58
|
+
/**
|
|
59
|
+
* Optional metadata about the samples.
|
|
60
|
+
*/
|
|
61
|
+
data?: Data;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Explicitly specify the sample attributes.
|
|
65
|
+
*/
|
|
66
|
+
attributes?: Record<string, SampleAttributeDef>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Text in the label title
|
|
70
|
+
*
|
|
71
|
+
* **Default:** `"Sample name"`
|
|
72
|
+
*/
|
|
73
|
+
labelTitleText?: string;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* How much space in pixels to reserve for the labels.
|
|
77
|
+
*
|
|
78
|
+
* **Default:** `140`
|
|
79
|
+
*/
|
|
80
|
+
labelLength?: number;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The font typeface. GenomeSpy uses [SDF](https://github.com/Chlumsky/msdfgen)
|
|
84
|
+
* versions of [Google Fonts](https://fonts.google.com/). Check their
|
|
85
|
+
* availability at the [A-Frame
|
|
86
|
+
* Fonts](https://github.com/etiennepinchon/aframe-fonts/tree/master/fonts)
|
|
87
|
+
* repository. System fonts are **not** supported.
|
|
88
|
+
*
|
|
89
|
+
* **Default value:** `"Lato"`
|
|
90
|
+
*/
|
|
91
|
+
labelFont?: string;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The font style. Valid values: `"normal"` and `"italic"`.
|
|
95
|
+
*
|
|
96
|
+
* **Default value:** `"normal"`
|
|
97
|
+
*/
|
|
98
|
+
labelFontStyle?: FontStyle;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The font weight. The following strings and numbers are valid values:
|
|
102
|
+
* `"thin"` (`100`), `"light"` (`300`), `"regular"` (`400`),
|
|
103
|
+
* `"normal"` (`400`), `"medium"` (`500`), `"bold"` (`700`),
|
|
104
|
+
* `"black"` (`900`)
|
|
105
|
+
*
|
|
106
|
+
* **Default value:** `"regular"`
|
|
107
|
+
*/
|
|
108
|
+
labelFontWeight?: FontWeight;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The font size in pixels.
|
|
112
|
+
*
|
|
113
|
+
* **Default value:** `11`
|
|
114
|
+
*/
|
|
115
|
+
labelFontSize?: number;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The horizontal alignment of the text. One of `"left"`, `"center"`, or `"right"`.
|
|
119
|
+
*
|
|
120
|
+
* **Default value:** `"left"`
|
|
121
|
+
*/
|
|
122
|
+
labelAlign?: Align;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Default size (width) of the metadata attribute columns.
|
|
126
|
+
* Can be configured per attribute using the `attributes` property.
|
|
127
|
+
*
|
|
128
|
+
* **Default value:** `10`
|
|
129
|
+
*/
|
|
130
|
+
attributeSize?: number;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The font typeface. GenomeSpy uses [SDF](https://github.com/Chlumsky/msdfgen)
|
|
134
|
+
* versions of [Google Fonts](https://fonts.google.com/). Check their
|
|
135
|
+
* availability at the [A-Frame
|
|
136
|
+
* Fonts](https://github.com/etiennepinchon/aframe-fonts/tree/master/fonts)
|
|
137
|
+
* repository. System fonts are **not** supported.
|
|
138
|
+
*
|
|
139
|
+
* **Default value:** `"Lato"`
|
|
140
|
+
*/
|
|
141
|
+
attributeLabelFont?: string;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The font style. Valid values: `"normal"` and `"italic"`.
|
|
145
|
+
*
|
|
146
|
+
* **Default value:** `"normal"`
|
|
147
|
+
*/
|
|
148
|
+
attributeLabelFontStyle?: FontStyle;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The font weight. The following strings and numbers are valid values:
|
|
152
|
+
* `"thin"` (`100`), `"light"` (`300`), `"regular"` (`400`),
|
|
153
|
+
* `"normal"` (`400`), `"medium"` (`500`), `"bold"` (`700`),
|
|
154
|
+
* `"black"` (`900`)
|
|
155
|
+
*
|
|
156
|
+
* **Default value:** `"regular"`
|
|
157
|
+
*/
|
|
158
|
+
attributeLabelFontWeight?: FontWeight;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The font size in pixels.
|
|
162
|
+
*
|
|
163
|
+
* **Default value:** `11`
|
|
164
|
+
*/
|
|
165
|
+
attributeLabelFontSize?: number;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Angle to be added to the default label angle (-90).
|
|
169
|
+
*
|
|
170
|
+
* **Default value:** `0`
|
|
171
|
+
*/
|
|
172
|
+
attributeLabelAngle?: number;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Spacing between attribute columns in pixels.
|
|
176
|
+
*
|
|
177
|
+
* **Default value:** `1`
|
|
178
|
+
*/
|
|
179
|
+
attributeSpacing?: number;
|
|
180
|
+
}
|
package/src/spec/transform.d.ts
CHANGED
|
@@ -156,14 +156,14 @@ export interface StackParams extends TransformParamsBase {
|
|
|
156
156
|
* Cardinality, e.g., the number if distinct bases or amino acids. Used for
|
|
157
157
|
* information content calculation when the offset is `"information"`.
|
|
158
158
|
*
|
|
159
|
-
* **Default:** `4
|
|
159
|
+
* **Default:** `4`
|
|
160
160
|
*/
|
|
161
161
|
cardinality?: number;
|
|
162
162
|
|
|
163
163
|
/**
|
|
164
164
|
* The field that contains the base or amino acid. Used for
|
|
165
165
|
* information content calculation when the offset is `"information"`.
|
|
166
|
-
* The data
|
|
166
|
+
* The data objects that have `null` in the baseField are considered gaps
|
|
167
167
|
* and they are taken into account when scaling the the locus' information
|
|
168
168
|
* content.
|
|
169
169
|
*/
|
package/src/spec/view.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { Data } from "./data";
|
|
2
|
-
import { Scale } from "./scale";
|
|
3
2
|
import { TransformParams } from "./transform";
|
|
4
3
|
import {
|
|
5
4
|
Channel,
|
|
6
5
|
Encoding,
|
|
7
6
|
FacetFieldDef,
|
|
8
7
|
PrimaryPositionalChannel,
|
|
9
|
-
Type,
|
|
10
8
|
} from "./channel";
|
|
11
9
|
import {
|
|
12
10
|
FillAndStrokeProps,
|
|
@@ -15,6 +13,7 @@ import {
|
|
|
15
13
|
RectProps,
|
|
16
14
|
} from "./mark";
|
|
17
15
|
import { Title } from "./title";
|
|
16
|
+
import { SampleSpec } from "./sampleView";
|
|
18
17
|
|
|
19
18
|
export interface SizeDef {
|
|
20
19
|
/** Size in pixels */
|
|
@@ -137,27 +136,6 @@ export interface FacetSpec extends ViewSpecBase {
|
|
|
137
136
|
spacing?: number;
|
|
138
137
|
}
|
|
139
138
|
|
|
140
|
-
export interface SampleAttributeDef {
|
|
141
|
-
type: Type; // TODO: Omit index/locus
|
|
142
|
-
/** Color scale (primary) */
|
|
143
|
-
scale?: Scale;
|
|
144
|
-
barScale?: Scale;
|
|
145
|
-
width?: number;
|
|
146
|
-
visible?: boolean;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export interface SampleDef {
|
|
150
|
-
data?: Data;
|
|
151
|
-
attributes?: Record<string, SampleAttributeDef>;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export interface SampleSpec extends ViewSpecBase {
|
|
155
|
-
samples: SampleDef;
|
|
156
|
-
spec: LayerSpec | UnitSpec;
|
|
157
|
-
|
|
158
|
-
stickySummaries?: boolean;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
139
|
export type ResolutionTarget = "scale" | "axis";
|
|
162
140
|
|
|
163
141
|
/**
|
|
@@ -30,20 +30,24 @@ export default async function dataTooltipHandler(datum, mark, params) {
|
|
|
30
30
|
return "";
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
const strippedEntries = Object.entries(datum).filter(
|
|
34
|
+
([key, _value]) => !key.startsWith("_")
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (strippedEntries.length === 0) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
const table = html`
|
|
34
42
|
<table class="attributes">
|
|
35
|
-
${
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
</td>
|
|
44
|
-
</tr>
|
|
45
|
-
`
|
|
46
|
-
)}
|
|
43
|
+
${strippedEntries.map(
|
|
44
|
+
([key, value]) => html`
|
|
45
|
+
<tr>
|
|
46
|
+
<th>${key}</th>
|
|
47
|
+
<td>${formatObject(value)} ${legend(key, datum)}</td>
|
|
48
|
+
</tr>
|
|
49
|
+
`
|
|
50
|
+
)}
|
|
47
51
|
</table>
|
|
48
52
|
`;
|
|
49
53
|
|
package/src/view/gridView.js
CHANGED
|
@@ -527,7 +527,11 @@ export default class GridView extends ContainerView {
|
|
|
527
527
|
return;
|
|
528
528
|
}
|
|
529
529
|
|
|
530
|
-
|
|
530
|
+
if (!this.parent) {
|
|
531
|
+
// Usually padding is applied by the parent GridView, but if this is the root view, we need to apply it here
|
|
532
|
+
coords = coords.shrink(this.getPadding());
|
|
533
|
+
}
|
|
534
|
+
|
|
531
535
|
context.pushView(this, coords);
|
|
532
536
|
|
|
533
537
|
const flexOpts = {
|
|
@@ -725,7 +729,7 @@ export default class GridView extends ContainerView {
|
|
|
725
729
|
* @param {import("../spec/view").ViewBackground} viewBackground
|
|
726
730
|
* @returns {import("../spec/view").UnitSpec}
|
|
727
731
|
*/
|
|
728
|
-
function createBackground(viewBackground) {
|
|
732
|
+
export function createBackground(viewBackground) {
|
|
729
733
|
return {
|
|
730
734
|
configurableVisibility: false,
|
|
731
735
|
data: { values: [{}] },
|