@jbrowse/wiggle-core 4.3.0 → 5.0.0-beta.10

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 (73) hide show
  1. package/README.md +76 -107
  2. package/esm/AutoscaleGroupDialog.d.ts +7 -0
  3. package/esm/AutoscaleGroupDialog.js +26 -0
  4. package/esm/ScoreAxisMixin.d.ts +134 -0
  5. package/esm/ScoreAxisMixin.js +213 -0
  6. package/esm/ScoreFieldConfigMixin.d.ts +72 -0
  7. package/esm/ScoreFieldConfigMixin.js +25 -0
  8. package/esm/ScorePlotChrome.d.ts +45 -0
  9. package/esm/ScorePlotChrome.js +47 -0
  10. package/esm/ScorePlotSvgFrame.d.ts +27 -0
  11. package/esm/ScorePlotSvgFrame.js +23 -0
  12. package/esm/ScoreScaleMixin.d.ts +113 -50
  13. package/esm/ScoreScaleMixin.js +148 -70
  14. package/esm/SetMinMaxDialog.d.ts +3 -2
  15. package/esm/SetMinMaxDialog.js +20 -6
  16. package/esm/SetScoreRulesDialog.d.ts +14 -0
  17. package/esm/SetScoreRulesDialog.js +45 -0
  18. package/esm/WiggleScoreConfigMixin.d.ts +89 -0
  19. package/esm/WiggleScoreConfigMixin.js +54 -0
  20. package/esm/autoscale.d.ts +54 -14
  21. package/esm/autoscale.js +105 -180
  22. package/esm/autoscaleGroup.d.ts +30 -0
  23. package/esm/autoscaleGroup.js +97 -0
  24. package/esm/chrome.d.ts +5 -0
  25. package/esm/chrome.js +7 -0
  26. package/esm/computeYTicks.d.ts +1 -1
  27. package/esm/computeYTicks.js +4 -3
  28. package/esm/constants.d.ts +1 -2
  29. package/esm/constants.js +1 -10
  30. package/esm/dataTypes.d.ts +4 -6
  31. package/esm/displayModel.d.ts +1 -2
  32. package/esm/gapBreak.d.ts +2 -3
  33. package/esm/gapBreak.js +2 -3
  34. package/esm/index.d.ts +24 -25
  35. package/esm/index.js +20 -18
  36. package/esm/normalize.d.ts +1 -26
  37. package/esm/normalize.js +1 -86
  38. package/esm/pointMarker.d.ts +7 -2
  39. package/esm/pointMarker.js +14 -18
  40. package/esm/pointSizeMenu.d.ts +30 -11
  41. package/esm/pointSizeMenu.js +42 -19
  42. package/esm/renderingBackendTypes.d.ts +13 -4
  43. package/esm/renderingBackendTypes.js +4 -1
  44. package/esm/rowLabelOffset.d.ts +8 -0
  45. package/esm/rowLabelOffset.js +16 -0
  46. package/esm/scale.d.ts +12 -8
  47. package/esm/scale.js +27 -14
  48. package/esm/scoreFieldConfigSchemaFields.d.ts +10 -0
  49. package/esm/scoreFieldConfigSchemaFields.js +8 -0
  50. package/esm/scoreMenuItems.d.ts +35 -16
  51. package/esm/scoreMenuItems.js +95 -62
  52. package/esm/scoreRuleMarks.d.ts +14 -39
  53. package/esm/scoreRuleMarks.js +12 -45
  54. package/esm/transferables.js +4 -9
  55. package/esm/valueScaleConfigSchema.d.ts +253 -0
  56. package/esm/valueScaleConfigSchema.js +270 -0
  57. package/esm/visibleStatsDomain.d.ts +20 -8
  58. package/esm/visibleStatsDomain.js +32 -27
  59. package/esm/wiggleRenderModes.generated.d.ts +1 -2
  60. package/esm/wiggleRenderModes.generated.js +1 -2
  61. package/package.json +14 -9
  62. package/esm/CrossHatches.d.ts +0 -11
  63. package/esm/CrossHatches.js +0 -32
  64. package/esm/ScoreRules.d.ts +0 -11
  65. package/esm/ScoreRules.js +0 -37
  66. package/esm/YScaleBar.d.ts +0 -6
  67. package/esm/YScaleBar.js +0 -46
  68. package/esm/YScaleBarOverlay.d.ts +0 -6
  69. package/esm/YScaleBarOverlay.js +0 -24
  70. package/esm/scoreAxisConfigSchemaFields.d.ts +0 -44
  71. package/esm/scoreAxisConfigSchemaFields.js +0 -54
  72. package/esm/yScaleTicks.d.ts +0 -59
  73. package/esm/yScaleTicks.js +0 -59
package/esm/index.d.ts CHANGED
@@ -1,34 +1,33 @@
1
- export { scoreAxisConfigSchemaFields } from './scoreAxisConfigSchemaFields.ts';
2
- export type { ScoreAxisConfigModel } from './scoreAxisConfigSchemaFields.ts';
1
+ export { retiredAxisSpellings, scalesSchema, valueScaleSchema, } from './valueScaleConfigSchema.ts';
2
+ export type { ScalesConfigSchema, ValueScaleConfigSchema, ValueScaleOptions, } from './valueScaleConfigSchema.ts';
3
3
  export { getNiceDomain, getNiceScale, getScale } from './scale.ts';
4
4
  export type { ScaleOpts } from './scale.ts';
5
5
  export { toP } from './formatNumber.ts';
6
- export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, resolveSymlogConstant, scaleTypeFromString, } from './normalize.ts';
7
- export type { WiggleScaleType } from './normalize.ts';
8
- export { autoscaleDomainFromStats, computeAutoscaleDomain, computeScoreStats, domainFromStats, getEffectiveScores, } from './autoscale.ts';
9
- export type { Dataset, FeatureArrays, ScoreStats } from './autoscale.ts';
10
- export { ONSCREEN_AXIS_LEFT_PX, YSCALEBAR_LABEL_OFFSET } from './constants.ts';
6
+ export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, resolveSymlogConstant, } from './normalize.ts';
7
+ export { autoscaleDomainFromSpans, autoscaleDomainFromStats, computeAutoscaleDomain, computeScoreStats, computeSpanStats, datasetSpan, getEffectiveScores, } from './autoscale.ts';
8
+ export type { Dataset, FeatureArrays, ScoreSpan, ScoreStats, } from './autoscale.ts';
9
+ export { axisDrawn } from '@jbrowse/display-ui/axisPlacement';
10
+ export { DEFAULT_RULE_COLOR, SCORE_CAPTION_HEIGHT, YSCALEBAR_LABEL_OFFSET, } from '@jbrowse/display-ui/yAxisConstants';
11
+ export { AXIS_GUTTER_WIDTH_PX, axisPlotBox, clampStrokeInsideAxis, scoreToAxisY, } from '@jbrowse/display-ui/yScaleTicks';
12
+ export type { ValueScale, ValueScaleRule, YAxis, YScaleTicks, } from '@jbrowse/display-ui';
11
13
  export { computeYTicks } from './computeYTicks.ts';
14
+ export { rowLabelOffset } from './rowLabelOffset.ts';
12
15
  export { resolveRenderState } from './resolveRenderState.ts';
13
- export { visibleStatsDomain } from './visibleStatsDomain.ts';
14
- export type { SettledBlocksView, VisibleEntry, VisibleStatsDomainSpec, } from './visibleStatsDomain.ts';
15
- export { AXIS_GUTTER_WIDTH_PX, axisPlotBox, clampStrokeInsideAxis, leftAxisSpineX, scoreToAxisY, } from './yScaleTicks.ts';
16
- export type { YScaleTicks } from './yScaleTicks.ts';
17
- export { CrossHatchLines, default as CrossHatches } from './CrossHatches.tsx';
18
- export { ScoreRuleLines, default as ScoreRules } from './ScoreRules.tsx';
19
- export { parseScoreRules, scoreRuleMarks, widenRangeToRules, } from './scoreRuleMarks.ts';
20
- export type { ScoreRule, ScoreRuleMark } from './scoreRuleMarks.ts';
21
- export { makeResolutionSubMenuItem } from './ResolutionStepper.tsx';
22
- export { makeScatterPointSizeMenuItem } from './pointSizeMenu.tsx';
23
- export { SMALL_POINT_MAX_DIAMETER_PX, appendPointMarker, } from './pointMarker.ts';
24
- export { default as SetMinMaxDialog } from './SetMinMaxDialog.tsx';
25
- export { DEFAULT_AUTOSCALE_OPTIONS } from './autoscale.ts';
26
- export { makeAutoscaleTypeSubMenu, makeCrossHatchItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.ts';
27
- export type { ScoreScaleModel } from './scoreMenuItems.ts';
16
+ export { visibleStatsDomain, visibleStatsRange } from './visibleStatsDomain.ts';
17
+ export type { SettledBlocksView, VisibleEntry, VisibleStatsDomainSpec, VisibleStatsRangeSpec, } from './visibleStatsDomain.ts';
18
+ export { scoreRuleMarks, widenRangeToRules } from './scoreRuleMarks.ts';
19
+ export type { ScoreRuleMark } from './scoreRuleMarks.ts';
20
+ export { DEFAULT_POINT_DIAMETER_PX, SMALL_POINT_MAX_DIAMETER_PX, appendPointMarker, } from './pointMarker.ts';
21
+ export { makeClipOutliersItem, AXIS_ZERO_LABEL, makeAxisZeroItem, makeCrossHatchItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.ts';
22
+ export type { ScoreScaleModel, ScoreSubMenuOptions } from './scoreMenuItems.ts';
23
+ export { ScoreAxisMixin } from './ScoreAxisMixin.ts';
28
24
  export { ScoreScaleMixin } from './ScoreScaleMixin.ts';
29
- export { default as YScaleBar } from './YScaleBar.tsx';
30
- export { default as YScaleBarOverlay } from './YScaleBarOverlay.tsx';
31
- export { MIN_FILL_WIDTH_PX, NO_PREV_START, RENDERING_TYPE_DENSITY, RENDERING_TYPE_LINE, RENDERING_TYPE_LINE_CENTER, RENDERING_TYPE_SCATTER, RENDERING_TYPE_XYPLOT, } from './renderingBackendTypes.ts';
25
+ export type { ScoreScaleHost } from './ScoreScaleMixin.ts';
26
+ export { WiggleScoreConfigMixin, wiggleScoreConfigExtraSlots, } from './WiggleScoreConfigMixin.ts';
27
+ export type { WiggleScoreConfigHost } from './WiggleScoreConfigMixin.ts';
28
+ export { ScoreFieldConfigMixin } from './ScoreFieldConfigMixin.ts';
29
+ export { DEFAULT_SCORE_FIELD, scoreFieldConfigSchemaFields, } from './scoreFieldConfigSchemaFields.ts';
30
+ export { MAX_WIGGLE_CUTS, MIN_FILL_WIDTH_PX, NO_PREV_START, RENDERING_TYPE_DENSITY, RENDERING_TYPE_LINE, RENDERING_TYPE_LINE_CENTER, RENDERING_TYPE_SCATTER, RENDERING_TYPE_XYPLOT, } from './renderingBackendTypes.ts';
32
31
  export type { SourceRenderData, WiggleGPURenderState, WiggleRenderingBackend, WiggleRenderingType, } from './renderingBackendTypes.ts';
33
32
  export type { SourceInfo, WiggleDataResult, WiggleFeatureArrays, WiggleSourceData, } from './dataTypes.ts';
34
33
  export { type WiggleGpuDisplayModel } from './displayModel.ts';
package/esm/index.js CHANGED
@@ -1,26 +1,28 @@
1
- export { scoreAxisConfigSchemaFields } from './scoreAxisConfigSchemaFields.js';
1
+ export { retiredAxisSpellings, scalesSchema, valueScaleSchema, } from './valueScaleConfigSchema.js';
2
2
  export { getNiceDomain, getNiceScale, getScale } from './scale.js';
3
3
  export { toP } from './formatNumber.js';
4
- export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, resolveSymlogConstant, scaleTypeFromString, } from './normalize.js';
5
- export { autoscaleDomainFromStats, computeAutoscaleDomain, computeScoreStats, domainFromStats, getEffectiveScores, } from './autoscale.js';
6
- export { ONSCREEN_AXIS_LEFT_PX, YSCALEBAR_LABEL_OFFSET } from './constants.js';
4
+ export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, resolveSymlogConstant, } from './normalize.js';
5
+ export { autoscaleDomainFromSpans, autoscaleDomainFromStats, computeAutoscaleDomain, computeScoreStats, computeSpanStats, datasetSpan, getEffectiveScores, } from './autoscale.js';
6
+ // The y-axis geometry, named at its own subpaths rather than through the
7
+ // `@jbrowse/display-ui` barrel: the barrel reaches react-dom, and reaching it
8
+ // from here put the score math and the three config mixins behind a worker
9
+ // stub. The components that draw the axis are `./chrome`.
10
+ export { axisDrawn } from '@jbrowse/display-ui/axisPlacement';
11
+ export { DEFAULT_RULE_COLOR, SCORE_CAPTION_HEIGHT, YSCALEBAR_LABEL_OFFSET, } from '@jbrowse/display-ui/yAxisConstants';
12
+ export { AXIS_GUTTER_WIDTH_PX, axisPlotBox, clampStrokeInsideAxis, scoreToAxisY, } from '@jbrowse/display-ui/yScaleTicks';
7
13
  export { computeYTicks } from './computeYTicks.js';
14
+ export { rowLabelOffset } from './rowLabelOffset.js';
8
15
  export { resolveRenderState } from './resolveRenderState.js';
9
- export { visibleStatsDomain } from './visibleStatsDomain.js';
10
- export { AXIS_GUTTER_WIDTH_PX, axisPlotBox, clampStrokeInsideAxis, leftAxisSpineX, scoreToAxisY, } from './yScaleTicks.js';
11
- export { CrossHatchLines, default as CrossHatches } from './CrossHatches.js';
12
- export { ScoreRuleLines, default as ScoreRules } from './ScoreRules.js';
13
- export { parseScoreRules, scoreRuleMarks, widenRangeToRules, } from './scoreRuleMarks.js';
14
- export { makeResolutionSubMenuItem } from './ResolutionStepper.js';
15
- export { makeScatterPointSizeMenuItem } from './pointSizeMenu.js';
16
- export { SMALL_POINT_MAX_DIAMETER_PX, appendPointMarker, } from './pointMarker.js';
17
- export { default as SetMinMaxDialog } from './SetMinMaxDialog.js';
18
- export { DEFAULT_AUTOSCALE_OPTIONS } from './autoscale.js';
19
- export { makeAutoscaleTypeSubMenu, makeCrossHatchItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.js';
16
+ export { visibleStatsDomain, visibleStatsRange } from './visibleStatsDomain.js';
17
+ export { scoreRuleMarks, widenRangeToRules } from './scoreRuleMarks.js';
18
+ export { DEFAULT_POINT_DIAMETER_PX, SMALL_POINT_MAX_DIAMETER_PX, appendPointMarker, } from './pointMarker.js';
19
+ export { makeClipOutliersItem, AXIS_ZERO_LABEL, makeAxisZeroItem, makeCrossHatchItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.js';
20
+ export { ScoreAxisMixin } from './ScoreAxisMixin.js';
20
21
  export { ScoreScaleMixin } from './ScoreScaleMixin.js';
21
- export { default as YScaleBar } from './YScaleBar.js';
22
- export { default as YScaleBarOverlay } from './YScaleBarOverlay.js';
23
- export { MIN_FILL_WIDTH_PX, NO_PREV_START, RENDERING_TYPE_DENSITY, RENDERING_TYPE_LINE, RENDERING_TYPE_LINE_CENTER, RENDERING_TYPE_SCATTER, RENDERING_TYPE_XYPLOT, } from './renderingBackendTypes.js';
22
+ export { WiggleScoreConfigMixin, wiggleScoreConfigExtraSlots, } from './WiggleScoreConfigMixin.js';
23
+ export { ScoreFieldConfigMixin } from './ScoreFieldConfigMixin.js';
24
+ export { DEFAULT_SCORE_FIELD, scoreFieldConfigSchemaFields, } from './scoreFieldConfigSchemaFields.js';
25
+ export { MAX_WIGGLE_CUTS, MIN_FILL_WIDTH_PX, NO_PREV_START, RENDERING_TYPE_DENSITY, RENDERING_TYPE_LINE, RENDERING_TYPE_LINE_CENTER, RENDERING_TYPE_SCATTER, RENDERING_TYPE_XYPLOT, } from './renderingBackendTypes.js';
24
26
  export {} from './displayModel.js';
25
27
  export { collectWiggleTransferables } from './transferables.js';
26
28
  export { DEFAULT_GAP_BREAK_MULTIPLE, gapBreakLimit } from './gapBreak.js';
@@ -1,13 +1,4 @@
1
- export type WiggleScaleType = 0 | 1 | 2;
2
- export declare const SCALE_TYPE_LINEAR: WiggleScaleType;
3
- export declare const SCALE_TYPE_LOG: WiggleScaleType;
4
- export declare const SCALE_TYPE_SYMLOG: WiggleScaleType;
5
- /**
6
- * #api
7
- * Maps the `'log'`/`'symlog'`/`'linear'` string to the numeric
8
- * `WiggleScaleType`.
9
- */
10
- export declare function scaleTypeFromString(scaleType: string): WiggleScaleType;
1
+ export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, } from '@jbrowse/render-core/scoreScale';
11
2
  /**
12
3
  * #api
13
4
  * The symlog constant actually used for a domain. `0` (the config default)
@@ -22,19 +13,3 @@ export declare function scaleTypeFromString(scaleType: string): WiggleScaleType;
22
13
  * rather than hard-coded.
23
14
  */
24
15
  export declare function resolveSymlogConstant(min: number, max: number, configured: number): number;
25
- /**
26
- * #api
27
- * Returns a loop-hoistable function normalizing a score to [0,1].
28
- *
29
- * `symlogConstant` is only read for `SCALE_TYPE_SYMLOG`, and is expected to be
30
- * already resolved by {@link resolveSymlogConstant} — the shader gets the same
31
- * resolved number as a uniform, so the "auto" rule lives on this side only and
32
- * the two backends compare like for like.
33
- *
34
- * A range that is zero **or negative** normalizes everything to 0, which is the
35
- * rule `scoreScale.slang` spells as `range <= 0.0`. Testing `range === 0` here
36
- * instead let a descending domain through to a negative `1 / range`, so every
37
- * score saturated to 1 on this side while the shader flattened them all to 0 —
38
- * one view, opposite plots. `normalizeScoreParity.test.ts` sweeps the two.
39
- */
40
- export declare function makeScoreNormalizer(min: number, max: number, scaleType: WiggleScaleType, symlogConstant?: number): (score: number) => number;
package/esm/normalize.js CHANGED
@@ -1,24 +1,4 @@
1
- import { SCALE_TYPE_LOG as GENERATED_SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG as GENERATED_SCALE_TYPE_SYMLOG, } from './wiggleRenderModes.generated.js';
2
- export const SCALE_TYPE_LINEAR = 0;
3
- // The values the `scaleType` uniform is compared against, so they are
4
- // wiggle.slang's own — generated in by `pnpm gen:shaders` (adr-051). LINEAR is
5
- // simply "neither of these".
6
- export const SCALE_TYPE_LOG = GENERATED_SCALE_TYPE_LOG;
7
- export const SCALE_TYPE_SYMLOG = GENERATED_SCALE_TYPE_SYMLOG;
8
- /**
9
- * #api
10
- * Maps the `'log'`/`'symlog'`/`'linear'` string to the numeric
11
- * `WiggleScaleType`.
12
- */
13
- export function scaleTypeFromString(scaleType) {
14
- if (scaleType === 'log') {
15
- return SCALE_TYPE_LOG;
16
- }
17
- if (scaleType === 'symlog') {
18
- return SCALE_TYPE_SYMLOG;
19
- }
20
- return SCALE_TYPE_LINEAR;
21
- }
1
+ export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, } from '@jbrowse/render-core/scoreScale';
22
2
  /**
23
3
  * #api
24
4
  * The symlog constant actually used for a domain. `0` (the config default)
@@ -39,68 +19,3 @@ export function resolveSymlogConstant(min, max, configured) {
39
19
  const magnitude = Math.max(Math.abs(min), Math.abs(max));
40
20
  return magnitude > 0 ? magnitude / 1000 : 1;
41
21
  }
42
- /** sign(x) * log1p(|x / c|) — the transform d3's scaleSymlog applies. */
43
- function symlog(x, c) {
44
- return Math.sign(x) * Math.log1p(Math.abs(x / c));
45
- }
46
- /**
47
- * #api
48
- * Returns a loop-hoistable function normalizing a score to [0,1].
49
- *
50
- * `symlogConstant` is only read for `SCALE_TYPE_SYMLOG`, and is expected to be
51
- * already resolved by {@link resolveSymlogConstant} — the shader gets the same
52
- * resolved number as a uniform, so the "auto" rule lives on this side only and
53
- * the two backends compare like for like.
54
- *
55
- * A range that is zero **or negative** normalizes everything to 0, which is the
56
- * rule `scoreScale.slang` spells as `range <= 0.0`. Testing `range === 0` here
57
- * instead let a descending domain through to a negative `1 / range`, so every
58
- * score saturated to 1 on this side while the shader flattened them all to 0 —
59
- * one view, opposite plots. `normalizeScoreParity.test.ts` sweeps the two.
60
- */
61
- export function makeScoreNormalizer(min, max, scaleType, symlogConstant = 1) {
62
- if (scaleType === SCALE_TYPE_SYMLOG) {
63
- // No flooring, and no clamp of the domain away from zero: symlog is defined
64
- // across the whole real line, which is the point of offering it.
65
- const c = symlogConstant;
66
- const tMin = symlog(min, c);
67
- const tMax = symlog(max, c);
68
- const tRange = tMax - tMin;
69
- if (tRange <= 0) {
70
- return () => 0;
71
- }
72
- const invRange = 1 / tRange;
73
- return (score) => Math.max(0, Math.min(1, (symlog(score, c) - tMin) * invRange));
74
- }
75
- if (scaleType === SCALE_TYPE_LOG) {
76
- // Floor at the domain's own min, not at 1. A log domain can sit entirely
77
- // below 1 — a mappability track, a methylation fraction, any normalized
78
- // ratio — and `getNiceDomain` deliberately keeps it there, pinning min to 1
79
- // only when max > 1 (an explicit `minScore` bound can also land under 1 at
80
- // any max). Flooring at 1 collapsed logMin and logMax to 0 for all of
81
- // those, so `logRange === 0` and every score in the track normalized to 0:
82
- // a plot flat on the baseline under an axis that, reading the same domain
83
- // through d3, spread its ticks down the full height.
84
- //
85
- // Callers passing min = 0 — the four coverage draws, whose domain starts at
86
- // no reads — still floor at 1, which is where a depth axis starts.
87
- const floor = min > 0 ? min : 1;
88
- const logMin = Math.log2(floor);
89
- const logMax = Math.log2(Math.max(max, floor));
90
- const logRange = logMax - logMin;
91
- if (logRange <= 0) {
92
- return () => 0;
93
- }
94
- const invLogRange = 1 / logRange;
95
- return (score) => {
96
- const logScore = Math.log2(Math.max(score, floor));
97
- return Math.max(0, Math.min(1, (logScore - logMin) * invLogRange));
98
- };
99
- }
100
- const range = max - min;
101
- if (range <= 0) {
102
- return () => 0;
103
- }
104
- const invRange = 1 / range;
105
- return (score) => Math.max(0, Math.min(1, (score - min) * invRange));
106
- }
@@ -1,3 +1,8 @@
1
- import type { Ctx2D } from '@jbrowse/core/util/paintLayer';
1
+ import type { MarkContext2D } from '@jbrowse/render-core/marks';
2
2
  export declare const SMALL_POINT_MAX_DIAMETER_PX = 3;
3
- export declare function appendPointMarker(ctx: Ctx2D, cx: number, y: number, diameter: number): void;
3
+ /**
4
+ * The diameter the mark display draws points at by default,
5
+ * where points are the plot rather than one of wiggle's renderings.
6
+ */
7
+ export declare const DEFAULT_POINT_DIAMETER_PX = 4;
8
+ export declare function appendPointMarker(ctx: MarkContext2D, cx: number, y: number, diameter: number): void;
@@ -1,27 +1,23 @@
1
- import { crispSquareTopLeftPx } from '@jbrowse/render-core/shaders/pointGlyph';
1
+ import { appendGlyph } from '@jbrowse/render-core/marks/glyphPaint';
2
2
  import { SMALL_POINT_MAX_DIAMETER } from '@jbrowse/render-core/shaders/pointGlyphConsts';
3
+ import { GLYPH_DISC } from '@jbrowse/render-core/shaders/pointMarkConsts';
3
4
  // At/below a 3px diameter an antialiased disc reads as a blurry blob, so scatter
4
5
  // points draw as a crisp filled square below this threshold and an AA disc
5
6
  // above it. The value comes from pointGlyph.slang via `//! export-consts`, so
6
7
  // the two backends can't disagree about where the square/disc split is; the
7
8
  // alias keeps this module's long-standing public name.
8
9
  export const SMALL_POINT_MAX_DIAMETER_PX = SMALL_POINT_MAX_DIAMETER;
9
- // Append one scatter point marker to the current path, centered on (cx, y): a
10
- // crisp filled square at/below SMALL_POINT_MAX_DIAMETER_PX, else an antialiased
11
- // disc. Shared by the wiggle scatter and GWAS Manhattan Canvas2D paths so the
12
- // square/disc threshold can't drift between them or from the shader. The caller
13
- // owns ctx.beginPath()/ctx.fill() so many markers batch into one fill.
10
+ /**
11
+ * The diameter the mark display draws points at by default,
12
+ * where points are the plot rather than one of wiggle's renderings.
13
+ */
14
+ export const DEFAULT_POINT_DIAMETER_PX = 4;
15
+ // Append one scatter point marker to the current path, centered on (cx, y): the
16
+ // `point` shape's disc glyph, which is a crisp filled square at/below
17
+ // SMALL_POINT_MAX_DIAMETER_PX and an antialiased disc above it. Wiggle's
18
+ // scatter mode draws only that one glyph, so this is the shape's painter
19
+ // reached at a name that predates it. The caller owns
20
+ // ctx.beginPath()/ctx.fill() so many markers batch into one fill.
14
21
  export function appendPointMarker(ctx, cx, y, diameter) {
15
- const radius = diameter / 2;
16
- if (diameter <= SMALL_POINT_MAX_DIAMETER_PX) {
17
- // Snap the top-left to the pixel grid (round-half-up) so the crisp square's
18
- // fill lands on whole pixels instead of AA-blurring across columns/rows.
19
- // `crispSquareTopLeftPx` is generated from pointGlyph.slang (adr-051), so
20
- // this is the shader's snap rather than a re-derivation of it.
21
- ctx.rect(crispSquareTopLeftPx(cx, diameter), crispSquareTopLeftPx(y, diameter), diameter, diameter);
22
- }
23
- else {
24
- ctx.moveTo(cx + radius, y);
25
- ctx.arc(cx, y, radius, 0, Math.PI * 2);
26
- }
22
+ appendGlyph(ctx, GLYPH_DISC, cx, y, diameter);
27
23
  }
@@ -1,13 +1,32 @@
1
- import type { ConfigModelForFields, ResolvableDisplay } from '@jbrowse/core/configuration';
1
+ import type { ConfigModelForFields } from '@jbrowse/core/configuration';
2
2
  import type { MenuItem } from '@jbrowse/core/ui';
3
- export declare function makeScatterPointSizeMenuItem(self: {
4
- scatterPointSize: number;
5
- setScatterPointSize: (n?: number) => void;
6
- } & ResolvableDisplay<ConfigModelForFields<{
7
- scatterPointSize: {
8
- type: 'maybeNumber';
9
- promotedBase: number;
10
- };
11
- }>>, opts: {
3
+ /** Where a display keeps its point size: the value shown, its default, and the write. */
4
+ export interface PointSizeAccess {
5
+ value: () => number;
6
+ defaultValue: number;
7
+ set: (n?: number) => void;
8
+ }
9
+ /**
10
+ * The point size a display holding `WiggleScoreConfigMixin`'s `size` slot
11
+ * shows and writes.
12
+ */
13
+ export declare function pointSizeAccess(self: {
14
+ size: number;
15
+ setSize: (n?: number) => void;
16
+ configuration: ConfigModelForFields<{
17
+ size: {
18
+ type: 'number';
19
+ defaultValue: number;
20
+ };
21
+ }>;
22
+ }): PointSizeAccess;
23
+ /**
24
+ * A top-level submenu holding the point-size slider, or nothing where the plot
25
+ * draws no points, so every score plot's menu resets and clamps alike.
26
+ * Top-level rather than under Score because the size describes the mark, not
27
+ * the axis.
28
+ */
29
+ export declare function makePointSizeSubMenu({ label, applies, value, defaultValue, set, }: PointSizeAccess & {
12
30
  label: string;
13
- }): MenuItem;
31
+ applies: boolean;
32
+ }): MenuItem[];
@@ -1,21 +1,44 @@
1
- import { makePromotableSizeMenu } from '@jbrowse/core/ui';
2
- // Wires a display's shared `scatterPointSize`/`setScatterPointSize` (from
3
- // WiggleScoreConfigMixin) to makePromotableSizeMenu. Used by both the wiggle
4
- // scatter and GWAS Manhattan track menus so the slider/reset/pin behavior can't
5
- // drift. The `scatterPointSize` slot is promotable, so the row carries the
6
- // "default for all tracks of this type" pin.
7
- export function makeScatterPointSizeMenuItem(self, opts) {
8
- return makePromotableSizeMenu({
9
- label: opts.label,
10
- title: 'Point size',
11
- display: self,
12
- slot: 'scatterPointSize',
13
- getValue: () => self.scatterPointSize,
14
- onChange: n => {
15
- self.setScatterPointSize(n);
1
+ import { getSlotDefinition } from '@jbrowse/core/configuration';
2
+ import { makeSizeMenu } from '@jbrowse/core/ui';
3
+ import ScatterPlotIcon from '@mui/icons-material/ScatterPlot';
4
+ /**
5
+ * The point size a display holding `WiggleScoreConfigMixin`'s `size` slot
6
+ * shows and writes.
7
+ */
8
+ export function pointSizeAccess(self) {
9
+ return {
10
+ value: () => self.size,
11
+ defaultValue: Number(getSlotDefinition(self.configuration, 'size').defaultValue),
12
+ set: n => {
13
+ self.setSize(n);
16
14
  },
17
- onReset: () => {
18
- self.setScatterPointSize(undefined);
19
- },
20
- });
15
+ };
16
+ }
17
+ /**
18
+ * A top-level submenu holding the point-size slider, or nothing where the plot
19
+ * draws no points, so every score plot's menu resets and clamps alike.
20
+ * Top-level rather than under Score because the size describes the mark, not
21
+ * the axis.
22
+ */
23
+ export function makePointSizeSubMenu({ label, applies, value, defaultValue, set, }) {
24
+ return applies
25
+ ? [
26
+ {
27
+ label,
28
+ icon: ScatterPlotIcon,
29
+ subMenu: [
30
+ makeSizeMenu({
31
+ label,
32
+ title: 'Point size',
33
+ getValue: value,
34
+ isDefault: value() === defaultValue,
35
+ onChange: set,
36
+ onReset: () => {
37
+ set();
38
+ },
39
+ }),
40
+ ],
41
+ },
42
+ ]
43
+ : [];
21
44
  }
@@ -1,5 +1,5 @@
1
- import type { WiggleScaleType } from './normalize.ts';
2
1
  import type { PerRegionRenderingBackend } from '@jbrowse/render-core/perRegionRenderingBackend';
2
+ import type { ScaleTypeCode } from '@jbrowse/render-core/scoreScale';
3
3
  export type WiggleRenderingType = 0 | 1 | 2 | 3 | 4;
4
4
  export declare const RENDERING_TYPE_XYPLOT: WiggleRenderingType;
5
5
  export declare const RENDERING_TYPE_DENSITY: WiggleRenderingType;
@@ -8,9 +8,10 @@ export declare const RENDERING_TYPE_SCATTER: WiggleRenderingType;
8
8
  export declare const RENDERING_TYPE_LINE_CENTER: WiggleRenderingType;
9
9
  export declare const NO_PREV_START = 4294967295;
10
10
  export declare const MIN_FILL_WIDTH_PX = 1.5;
11
+ export declare const MAX_WIGGLE_CUTS = 8;
11
12
  export interface WiggleGPURenderState {
12
13
  domainY: [number, number];
13
- scaleType: WiggleScaleType;
14
+ scaleType: ScaleTypeCode;
14
15
  /**
15
16
  * symlog's linear-region width, already resolved from the domain by
16
17
  * `resolveSymlogConstant`. Both backends read this one number so the axis,
@@ -21,10 +22,14 @@ export interface WiggleGPURenderState {
21
22
  canvasWidth: number;
22
23
  canvasHeight: number;
23
24
  numRows: number;
24
- scatterPointSize: number;
25
+ diameterPx: number;
25
26
  lineWidth: number;
26
27
  origin: number;
27
- densityColorRamp?: string;
28
+ pivot: number;
29
+ cuts: number[];
30
+ innerColors: [number, number, number][];
31
+ rampMid?: number;
32
+ rampLut?: Uint8Array;
28
33
  }
29
34
  export interface SourceRenderData {
30
35
  featurePositions: Uint32Array;
@@ -34,6 +39,10 @@ export interface SourceRenderData {
34
39
  rowIndex: number;
35
40
  renderingType: WiggleRenderingType;
36
41
  colorsAbgr?: Uint32Array;
42
+ negColor?: [number, number, number];
37
43
  gapLimitBp?: number;
44
+ band?: {
45
+ minScores: Float32Array;
46
+ };
38
47
  }
39
48
  export type WiggleRenderingBackend = PerRegionRenderingBackend<SourceRenderData[], WiggleGPURenderState>;
@@ -1,4 +1,4 @@
1
- import { MIN_FILL_WIDTH_PX as GENERATED_MIN_FILL_WIDTH_PX, NO_PREV_START as GENERATED_NO_PREV_START, RENDERING_TYPE_DENSITY as GENERATED_RENDERING_TYPE_DENSITY, RENDERING_TYPE_LINE as GENERATED_RENDERING_TYPE_LINE, RENDERING_TYPE_LINE_CENTER as GENERATED_RENDERING_TYPE_LINE_CENTER, RENDERING_TYPE_SCATTER as GENERATED_RENDERING_TYPE_SCATTER, RENDERING_TYPE_XYPLOT as GENERATED_RENDERING_TYPE_XYPLOT, } from './wiggleRenderModes.generated.js';
1
+ import { MAX_WIGGLE_CUTS as GENERATED_MAX_WIGGLE_CUTS, MIN_FILL_WIDTH_PX as GENERATED_MIN_FILL_WIDTH_PX, NO_PREV_START as GENERATED_NO_PREV_START, RENDERING_TYPE_DENSITY as GENERATED_RENDERING_TYPE_DENSITY, RENDERING_TYPE_LINE as GENERATED_RENDERING_TYPE_LINE, RENDERING_TYPE_LINE_CENTER as GENERATED_RENDERING_TYPE_LINE_CENTER, RENDERING_TYPE_SCATTER as GENERATED_RENDERING_TYPE_SCATTER, RENDERING_TYPE_XYPLOT as GENERATED_RENDERING_TYPE_XYPLOT, } from './wiggleRenderModes.generated.js';
2
2
  // The `renderingType` uniform's vocabulary. These are wiggle.slang's own
3
3
  // numbers, generated in by `pnpm gen:shaders` (adr-051): the Canvas2D path
4
4
  // branches on them to pick a draw function while the GPU path branches on them
@@ -27,3 +27,6 @@ export const NO_PREV_START = GENERATED_NO_PREV_START;
27
27
  // It was a `1.5` in each, kept together by a comment in each pointing at the
28
28
  // other.
29
29
  export const MIN_FILL_WIDTH_PX = GENERATED_MIN_FILL_WIDTH_PX;
30
+ // The most cuts a threshold colour parts a plot at: the shader's uniform
31
+ // block holds this many.
32
+ export const MAX_WIGGLE_CUTS = GENERATED_MAX_WIGGLE_CUTS;
@@ -0,0 +1,8 @@
1
+ import type { YAxis } from '@jbrowse/display-ui';
2
+ /**
3
+ * Where row labels start: `offset`, past the dendrogram, or past the axis each
4
+ * row repeats where one draws, since a label grows rightward over the plot.
5
+ * `exportContentLeft` is the export shell's, which moves an axis nothing
6
+ * pushes right into the margin, so the labels follow it there.
7
+ */
8
+ export declare function rowLabelOffset(axes: readonly YAxis[], offset: number, exportContentLeft?: number): number;
@@ -0,0 +1,16 @@
1
+ import { axisDrawn, axisGutterLeft, axisGutterWidth, } from '@jbrowse/display-ui/axisPlacement';
2
+ const AXIS_TO_LABEL_GAP_PX = 4;
3
+ /**
4
+ * Where row labels start: `offset`, past the dendrogram, or past the axis each
5
+ * row repeats where one draws, since a label grows rightward over the plot.
6
+ * `exportContentLeft` is the export shell's, which moves an axis nothing
7
+ * pushes right into the margin, so the labels follow it there.
8
+ */
9
+ export function rowLabelOffset(axes, offset, exportContentLeft) {
10
+ const axis = axes.find(axisDrawn);
11
+ return axis
12
+ ? Math.max(offset, axisGutterLeft(axis, 0, 0, exportContentLeft) +
13
+ axisGutterWidth(axis) +
14
+ AXIS_TO_LABEL_GAP_PX)
15
+ : offset;
16
+ }
package/esm/scale.d.ts CHANGED
@@ -20,7 +20,7 @@ export interface ScaleOpts {
20
20
  symlogConstant?: number;
21
21
  /**
22
22
  * Round the domain to nice endpoints before building the scale. Defaults to
23
- * true, which is what a caller handing over raw data wants. Pass false when
23
+ * true, for a caller handing over raw data. Pass false when
24
24
  * the domain is already the one something else is drawing with — nicing it
25
25
  * again moves the axis off that drawing, and can invent an endpoint outside
26
26
  * it (a raw `[1, 1000]` nices to `[1, 1024]`, so the axis labels a tick at a
@@ -36,18 +36,22 @@ export interface ScaleOpts {
36
36
  export declare function getScale({ domain, range, scaleType, symlogConstant, nice, }: ScaleOpts): Scale;
37
37
  /**
38
38
  * #api
39
- * Rounds a domain to "nice" endpoints, clamped to the origin. An end given an
40
- * explicit `bounds` value keeps that value exactly — only an autoscaled end is
41
- * rounded. A log scale's floor still outranks a bound it cannot hold.
39
+ * Rounds a domain to "nice" endpoints. `zero` reaches a linear or symlog
40
+ * domain to 0 (`scales.y.zero`, ADR-182); a log domain has no 0 and floors at
41
+ * 1 instead. An end given an explicit `bounds` value keeps that value exactly
42
+ * — only an autoscaled end is rounded. A log scale's floor still outranks a
43
+ * bound it cannot hold.
42
44
  *
43
- * The result never descends: a bound that would put `min` above `max` widens
44
- * the other end instead, so no consumer has to guess what a backwards domain
45
- * means.
45
+ * The result never descends and never collapses: a bound that would put `min`
46
+ * above `max` widens the other end instead, and one value in view widens
47
+ * away from itself, so no consumer has to guess what a backwards or a flat
48
+ * domain means.
46
49
  */
47
- export declare function getNiceDomain({ scaleType, domain, bounds, }: {
50
+ export declare function getNiceDomain({ scaleType, domain, bounds, zero, }: {
48
51
  scaleType: string;
49
52
  domain: readonly [number, number];
50
53
  bounds: readonly [number | undefined, number | undefined];
54
+ zero: boolean;
51
55
  }): [number, number];
52
56
  /**
53
57
  * #api
package/esm/scale.js CHANGED
@@ -64,24 +64,27 @@ export function getScale({ domain, range, scaleType, symlogConstant, nice = true
64
64
  }
65
65
  /**
66
66
  * #api
67
- * Rounds a domain to "nice" endpoints, clamped to the origin. An end given an
68
- * explicit `bounds` value keeps that value exactly — only an autoscaled end is
69
- * rounded. A log scale's floor still outranks a bound it cannot hold.
67
+ * Rounds a domain to "nice" endpoints. `zero` reaches a linear or symlog
68
+ * domain to 0 (`scales.y.zero`, ADR-182); a log domain has no 0 and floors at
69
+ * 1 instead. An end given an explicit `bounds` value keeps that value exactly
70
+ * — only an autoscaled end is rounded. A log scale's floor still outranks a
71
+ * bound it cannot hold.
70
72
  *
71
- * The result never descends: a bound that would put `min` above `max` widens
72
- * the other end instead, so no consumer has to guess what a backwards domain
73
- * means.
73
+ * The result never descends and never collapses: a bound that would put `min`
74
+ * above `max` widens the other end instead, and one value in view widens
75
+ * away from itself, so no consumer has to guess what a backwards or a flat
76
+ * domain means.
74
77
  */
75
78
  // No `symlogConstant` parameter: `niceDomain` puts symlog through d3's linear
76
79
  // path, which never reads the constant, so one passed here only looked like it
77
80
  // did something.
78
- export function getNiceDomain({ scaleType, domain, bounds, }) {
81
+ export function getNiceDomain({ scaleType, domain, bounds, zero, }) {
79
82
  const [minScore, maxScore] = bounds;
80
83
  let [min, max] = domain;
81
84
  // symlog joins linear here rather than log: it is defined at 0, so the
82
- // domain should reach the baseline its bars grow from instead of being
85
+ // domain can reach the baseline its bars grow from instead of being
83
86
  // floored off it the way a log domain has to be.
84
- if (scaleType === 'linear' || scaleType === 'symlog') {
87
+ if (zero && (scaleType === 'linear' || scaleType === 'symlog')) {
85
88
  if (max < 0) {
86
89
  max = 0;
87
90
  }
@@ -101,11 +104,9 @@ export function getNiceDomain({ scaleType, domain, bounds, }) {
101
104
  max = maxScore;
102
105
  }
103
106
  if (scaleType === 'log') {
104
- // d3 scaleLog is undefined at values <= 0, so autoscale (esp. localsd) or
105
- // data that crosses zero (e.g. log-ratio bigwigs) would otherwise yield a
106
- // domain that produces NaN ticks and a blank plot. Floor the domain to a
107
- // positive, non-degenerate range so the axis renders its valid portion
108
- // instead of silently disappearing.
107
+ // d3 scaleLog is undefined at values <= 0, so data crossing zero (a
108
+ // log-ratio bigwig) would yield NaN ticks and a blank plot; floor the
109
+ // domain to a positive, non-degenerate range instead.
109
110
  if (min <= 0) {
110
111
  min = max > 1 ? 1 : max > 0 ? max / 100 : 1;
111
112
  }
@@ -133,6 +134,18 @@ export function getNiceDomain({ scaleType, domain, bounds, }) {
133
134
  [min, max] = [max, min];
134
135
  }
135
136
  }
137
+ else if (max === min) {
138
+ // One value in view, which a domain reaching 0 never collapses on unless
139
+ // that value is 0. Flat, the normalizer steps at the value and every bar
140
+ // draws at 0 height; widen the free end by the value's own size.
141
+ const pad = Math.abs(min) || 1;
142
+ if (maxScore === undefined) {
143
+ max += pad;
144
+ }
145
+ else if (minScore === undefined) {
146
+ min -= pad;
147
+ }
148
+ }
136
149
  // Rounding is for an autoscaled end, whose only meaning is "roughly the
137
150
  // data's extent". A bound the user typed into Set min/max score means itself,
138
151
  // and the menu row goes on displaying it, so it is taken as given.
@@ -0,0 +1,10 @@
1
+ import type { ConfigModelForFields } from '@jbrowse/core/configuration';
2
+ export declare const DEFAULT_SCORE_FIELD = "score";
3
+ export declare const scoreFieldConfigSchemaFields: {
4
+ readonly scoreField: {
5
+ readonly type: 'string';
6
+ readonly defaultValue: "score";
7
+ readonly description: "Feature field plotted on the score axis, read natively off each feature. The default `score` is the field every adapter serves — including the value a BED adapter's `scoreColumn` rewrote it to — so an explicit name here reaches a raw column the adapter left alone (a BED extra column, a GFF attribute) and takes precedence over that adapter-tier rewrite. The Manhattan plot skips a feature with no finite value in the field; the wiggle renderings plot it at 0";
8
+ };
9
+ };
10
+ export type ScoreFieldConfigModel = ConfigModelForFields<typeof scoreFieldConfigSchemaFields>;
@@ -0,0 +1,8 @@
1
+ export const DEFAULT_SCORE_FIELD = 'score';
2
+ export const scoreFieldConfigSchemaFields = {
3
+ scoreField: {
4
+ type: 'string',
5
+ defaultValue: DEFAULT_SCORE_FIELD,
6
+ description: "Feature field plotted on the score axis, read natively off each feature. The default `score` is the field every adapter serves — including the value a BED adapter's `scoreColumn` rewrote it to — so an explicit name here reaches a raw column the adapter left alone (a BED extra column, a GFF attribute) and takes precedence over that adapter-tier rewrite. The Manhattan plot skips a feature with no finite value in the field; the wiggle renderings plot it at 0",
7
+ },
8
+ };