@jbrowse/wiggle-core 5.0.0-beta.7 → 5.0.0-beta.9

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 (47) hide show
  1. package/README.md +49 -83
  2. package/esm/ScoreAxisMixin.d.ts +99 -0
  3. package/esm/ScoreAxisMixin.js +150 -0
  4. package/esm/ScoreFieldConfigMixin.d.ts +60 -0
  5. package/esm/ScoreFieldConfigMixin.js +25 -0
  6. package/esm/ScorePlotChrome.d.ts +45 -0
  7. package/esm/ScorePlotChrome.js +47 -0
  8. package/esm/ScorePlotSvgFrame.d.ts +27 -0
  9. package/esm/ScorePlotSvgFrame.js +23 -0
  10. package/esm/ScoreScaleMixin.d.ts +65 -99
  11. package/esm/ScoreScaleMixin.js +78 -141
  12. package/esm/SetScoreRulesDialog.d.ts +14 -0
  13. package/esm/SetScoreRulesDialog.js +45 -0
  14. package/esm/WiggleScoreConfigMixin.d.ts +89 -0
  15. package/esm/WiggleScoreConfigMixin.js +69 -0
  16. package/esm/autoscale.d.ts +45 -5
  17. package/esm/autoscale.js +99 -67
  18. package/esm/chrome.d.ts +4 -0
  19. package/esm/chrome.js +7 -0
  20. package/esm/computeYTicks.d.ts +1 -1
  21. package/esm/computeYTicks.js +4 -2
  22. package/esm/dataTypes.d.ts +2 -6
  23. package/esm/gapBreak.d.ts +2 -3
  24. package/esm/gapBreak.js +2 -3
  25. package/esm/index.d.ts +20 -16
  26. package/esm/index.js +17 -13
  27. package/esm/normalize.d.ts +1 -26
  28. package/esm/normalize.js +1 -86
  29. package/esm/pointSizeMenu.d.ts +13 -0
  30. package/esm/pointSizeMenu.js +21 -3
  31. package/esm/renderingBackendTypes.d.ts +12 -3
  32. package/esm/renderingBackendTypes.js +4 -1
  33. package/esm/scale.d.ts +1 -1
  34. package/esm/scoreFieldConfigSchemaFields.d.ts +10 -0
  35. package/esm/scoreFieldConfigSchemaFields.js +11 -0
  36. package/esm/scoreMenuItems.d.ts +19 -7
  37. package/esm/scoreMenuItems.js +64 -29
  38. package/esm/scoreRuleMarks.d.ts +13 -37
  39. package/esm/scoreRuleMarks.js +12 -45
  40. package/esm/transferables.js +3 -8
  41. package/esm/valueScaleConfigSchema.d.ts +211 -0
  42. package/esm/valueScaleConfigSchema.js +240 -0
  43. package/esm/wiggleRenderModes.generated.d.ts +1 -2
  44. package/esm/wiggleRenderModes.generated.js +1 -2
  45. package/package.json +12 -8
  46. package/esm/scoreAxisConfigSchemaFields.d.ts +0 -44
  47. package/esm/scoreAxisConfigSchemaFields.js +0 -54
package/esm/index.d.ts CHANGED
@@ -1,29 +1,33 @@
1
- export { scoreAxisConfigSchemaFields } from './scoreAxisConfigSchemaFields.ts';
2
- export type { ScoreAxisConfigModel } from './scoreAxisConfigSchemaFields.ts';
1
+ export { scalesSchema, valueScaleSchema } from './valueScaleConfigSchema.ts';
2
+ export type { ScalesConfigSchema, ValueScaleAutoscale, 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 { AXIS_GUTTER_WIDTH_PX, AxisGutter, CrossHatchLines, CrossHatches, SCORE_CAPTION_HEIGHT, ScoreDomainCaption, ScoreRuleLines, ScoreRules, YSCALEBAR_LABEL_OFFSET, YScaleBar, YScaleBarOverlay, axisDrawn, axisPlotBox, clampStrokeInsideAxis, scoreToAxisY, } from '@jbrowse/display-ui';
11
- export type { ValueScale, YAxis, YScaleTicks } from '@jbrowse/display-ui';
6
+ export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, resolveSymlogConstant, } from './normalize.ts';
7
+ export { autoscaleDomainFromSpans, autoscaleDomainFromStats, computeAutoscaleDomain, computeScoreStats, computeSpanStats, datasetSpan, domainFromStats, 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';
12
13
  export { computeYTicks } from './computeYTicks.ts';
13
14
  export { resolveRenderState } from './resolveRenderState.ts';
14
15
  export { visibleStatsDomain } from './visibleStatsDomain.ts';
15
16
  export type { SettledBlocksView, VisibleEntry, VisibleStatsDomainSpec, } from './visibleStatsDomain.ts';
16
- export { parseScoreRules, scoreRuleMarks, widenRangeToRules, } from './scoreRuleMarks.ts';
17
- export type { ScoreRule, ScoreRuleMark } from './scoreRuleMarks.ts';
18
- export { makeResolutionSubMenuItem } from './ResolutionStepper.tsx';
19
- export { makeScatterPointSizeMenuItem } from './pointSizeMenu.tsx';
17
+ export { scoreRuleMarks, widenRangeToRules } from './scoreRuleMarks.ts';
18
+ export type { ScoreRuleMark } from './scoreRuleMarks.ts';
20
19
  export { SMALL_POINT_MAX_DIAMETER_PX, appendPointMarker, } from './pointMarker.ts';
21
- export { default as SetMinMaxDialog } from './SetMinMaxDialog.tsx';
22
20
  export { DEFAULT_AUTOSCALE_OPTIONS } from './autoscale.ts';
23
- export { makeAutoscaleTypeSubMenu, makeCrossHatchItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.ts';
24
- export type { ScoreScaleModel } from './scoreMenuItems.ts';
21
+ export { makeAutoscaleTypeSubMenu, makeCrossHatchItem, makePinCurrentRangeItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.ts';
22
+ export type { AutoscaleModel, ScoreScaleModel, ScoreSubMenuOptions, } from './scoreMenuItems.ts';
23
+ export { ScoreAxisMixin } from './ScoreAxisMixin.ts';
25
24
  export { ScoreScaleMixin } from './ScoreScaleMixin.ts';
26
- 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';
27
31
  export type { SourceRenderData, WiggleGPURenderState, WiggleRenderingBackend, WiggleRenderingType, } from './renderingBackendTypes.ts';
28
32
  export type { SourceInfo, WiggleDataResult, WiggleFeatureArrays, WiggleSourceData, } from './dataTypes.ts';
29
33
  export { type WiggleGpuDisplayModel } from './displayModel.ts';
package/esm/index.js CHANGED
@@ -1,24 +1,28 @@
1
- export { scoreAxisConfigSchemaFields } from './scoreAxisConfigSchemaFields.js';
1
+ export { 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
- // The y-axis primitives live in `@jbrowse/display-ui`, where the chrome
7
- // places them for any display declaring `valueScales`; re-exported here so
8
- // their published names hold.
9
- export { AXIS_GUTTER_WIDTH_PX, AxisGutter, CrossHatchLines, CrossHatches, SCORE_CAPTION_HEIGHT, ScoreDomainCaption, ScoreRuleLines, ScoreRules, YSCALEBAR_LABEL_OFFSET, YScaleBar, YScaleBarOverlay, axisDrawn, axisPlotBox, clampStrokeInsideAxis, scoreToAxisY, } from '@jbrowse/display-ui';
4
+ export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, resolveSymlogConstant, } from './normalize.js';
5
+ export { autoscaleDomainFromSpans, autoscaleDomainFromStats, computeAutoscaleDomain, computeScoreStats, computeSpanStats, datasetSpan, domainFromStats, 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';
10
13
  export { computeYTicks } from './computeYTicks.js';
11
14
  export { resolveRenderState } from './resolveRenderState.js';
12
15
  export { visibleStatsDomain } from './visibleStatsDomain.js';
13
- export { parseScoreRules, scoreRuleMarks, widenRangeToRules, } from './scoreRuleMarks.js';
14
- export { makeResolutionSubMenuItem } from './ResolutionStepper.js';
15
- export { makeScatterPointSizeMenuItem } from './pointSizeMenu.js';
16
+ export { scoreRuleMarks, widenRangeToRules } from './scoreRuleMarks.js';
16
17
  export { SMALL_POINT_MAX_DIAMETER_PX, appendPointMarker, } from './pointMarker.js';
17
- export { default as SetMinMaxDialog } from './SetMinMaxDialog.js';
18
18
  export { DEFAULT_AUTOSCALE_OPTIONS } from './autoscale.js';
19
- export { makeAutoscaleTypeSubMenu, makeCrossHatchItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.js';
19
+ export { makeAutoscaleTypeSubMenu, makeCrossHatchItem, makePinCurrentRangeItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.js';
20
+ export { ScoreAxisMixin } from './ScoreAxisMixin.js';
20
21
  export { ScoreScaleMixin } from './ScoreScaleMixin.js';
21
- 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';
22
26
  export {} from './displayModel.js';
23
27
  export { collectWiggleTransferables } from './transferables.js';
24
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,5 +1,9 @@
1
1
  import type { ConfigModelForFields } from '@jbrowse/core/configuration';
2
2
  import type { MenuItem } from '@jbrowse/core/ui';
3
+ /**
4
+ * The point-size slider row over `WiggleScoreConfigMixin`'s
5
+ * `scatterPointSize`, so every score plot's menu resets and clamps alike.
6
+ */
3
7
  export declare function makeScatterPointSizeMenuItem(self: {
4
8
  scatterPointSize: number;
5
9
  setScatterPointSize: (n?: number) => void;
@@ -12,3 +16,12 @@ export declare function makeScatterPointSizeMenuItem(self: {
12
16
  }, opts: {
13
17
  label: string;
14
18
  }): MenuItem;
19
+ /**
20
+ * A top-level submenu holding the point-size row, or nothing where the plot
21
+ * draws no points. Top-level rather than under Score because the size
22
+ * describes the mark, not the axis.
23
+ */
24
+ export declare function makePointSizeSubMenu(self: Parameters<typeof makeScatterPointSizeMenuItem>[0], { label, applies }: {
25
+ label: string;
26
+ applies: boolean;
27
+ }): MenuItem[];
@@ -1,8 +1,10 @@
1
1
  import { getSlotDefinition } from '@jbrowse/core/configuration';
2
2
  import { makeSizeMenu } from '@jbrowse/core/ui';
3
- // Wires a display's shared `scatterPointSize`/`setScatterPointSize` (from
4
- // WiggleScoreConfigMixin) to makeSizeMenu. Used by both the wiggle scatter and
5
- // GWAS Manhattan track menus so the slider/reset behavior can't drift.
3
+ import ScatterPlotIcon from '@mui/icons-material/ScatterPlot';
4
+ /**
5
+ * The point-size slider row over `WiggleScoreConfigMixin`'s
6
+ * `scatterPointSize`, so every score plot's menu resets and clamps alike.
7
+ */
6
8
  export function makeScatterPointSizeMenuItem(self, opts) {
7
9
  return makeSizeMenu({
8
10
  label: opts.label,
@@ -18,3 +20,19 @@ export function makeScatterPointSizeMenuItem(self, opts) {
18
20
  },
19
21
  });
20
22
  }
23
+ /**
24
+ * A top-level submenu holding the point-size row, or nothing where the plot
25
+ * draws no points. Top-level rather than under Score because the size
26
+ * describes the mark, not the axis.
27
+ */
28
+ export function makePointSizeSubMenu(self, { label, applies }) {
29
+ return applies
30
+ ? [
31
+ {
32
+ label,
33
+ icon: ScatterPlotIcon,
34
+ subMenu: [makeScatterPointSizeMenuItem(self, { label })],
35
+ },
36
+ ]
37
+ : [];
38
+ }
@@ -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,
@@ -24,7 +25,11 @@ export interface WiggleGPURenderState {
24
25
  scatterPointSize: 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;
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
@@ -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,11 @@
1
+ export const DEFAULT_SCORE_FIELD = 'score';
2
+ // One declaration for the three displays that plot a feature field on a score
3
+ // axis — the two wiggle displays and the Manhattan plot — so the slot has one
4
+ // name, one default and one description wherever it appears.
5
+ export const scoreFieldConfigSchemaFields = {
6
+ scoreField: {
7
+ type: 'string',
8
+ defaultValue: DEFAULT_SCORE_FIELD,
9
+ 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",
10
+ },
11
+ };
@@ -1,20 +1,30 @@
1
- import type { MenuItem } from '@jbrowse/core/ui';
1
+ import type { MenuItem, NormalMenuItem } from '@jbrowse/core/ui';
2
+ import type { ValueScaleRule } from '@jbrowse/display-ui';
2
3
  import type { IStateTreeNode } from '@jbrowse/mobx-state-tree';
3
4
  export interface ScoreScaleModel extends IStateTreeNode {
4
5
  scaleType: string;
5
- autoscaleType: string;
6
+ scaleTypeChoices: string[];
6
7
  manualMinScore: number | undefined;
7
8
  manualMaxScore: number | undefined;
8
9
  minScoreBound: number | undefined;
9
10
  maxScoreBound: number | undefined;
10
11
  hasManualScoreBounds: boolean;
11
12
  setScaleType: (v: string) => void;
12
- setAutoscale: (v?: string) => void;
13
13
  setMinScore: (n?: number) => void;
14
14
  setMaxScore: (n?: number) => void;
15
15
  }
16
+ export interface AutoscaleModel {
17
+ autoscaleType: string | undefined;
18
+ setAutoscale: (v?: string) => void;
19
+ }
20
+ export interface ScoreRulesModel {
21
+ scoreRulesDrawn: boolean;
22
+ scoreRules: ValueScaleRule[];
23
+ setScoreRules: (rules: ValueScaleRule[]) => void;
24
+ }
16
25
  export declare function makeScaleTypeSubMenu(self: {
17
26
  scaleType: string;
27
+ scaleTypeChoices: string[];
18
28
  setScaleType: (v: string) => void;
19
29
  }): MenuItem;
20
30
  export declare function makeAutoscaleTypeSubMenu(self: {
@@ -22,17 +32,19 @@ export declare function makeAutoscaleTypeSubMenu(self: {
22
32
  setAutoscale: (v?: string) => void;
23
33
  }, options?: [string, string][]): MenuItem;
24
34
  export declare function makeSetMinMaxScoreItem(self: ScoreScaleModel): MenuItem;
35
+ export declare function makePinCurrentRangeItem(self: ScoreScaleModel, domain: [number, number]): NormalMenuItem;
25
36
  export declare function makeCrossHatchItem(self: {
26
37
  displayCrossHatches: boolean;
27
38
  toggleCrossHatches: () => void;
28
39
  }): MenuItem;
29
- export declare function makeScoreSubMenu(self: ScoreScaleModel, opts?: {
40
+ export interface ScoreSubMenuOptions {
30
41
  label?: string;
31
- scaleType?: boolean;
32
- autoscale?: boolean;
33
42
  autoscaleOptions?: [string, string][];
43
+ domain?: [number, number];
34
44
  leadingItems?: MenuItem[];
35
45
  trailingItems?: MenuItem[];
36
46
  disabled?: boolean;
37
47
  disabledHelpText?: string;
38
- }): MenuItem;
48
+ }
49
+ export declare function makeSetScoreRulesItem(self: IStateTreeNode & ScoreRulesModel): MenuItem;
50
+ export declare function makeScoreSubMenu(self: ScoreScaleModel & Partial<AutoscaleModel> & Partial<ScoreRulesModel>, opts?: ScoreSubMenuOptions): MenuItem;
@@ -2,21 +2,26 @@ import { lazy } from 'react';
2
2
  import { checkboxItem, radioItems } from '@jbrowse/core/ui/menuItems';
3
3
  import { getDialogHost } from '@jbrowse/core/util';
4
4
  import EqualizerIcon from '@mui/icons-material/Equalizer';
5
+ import HorizontalRuleIcon from '@mui/icons-material/HorizontalRule';
5
6
  import { DEFAULT_AUTOSCALE_OPTIONS } from './autoscale.js';
6
7
  const SetMinMaxDialog = lazy(() => import('./SetMinMaxDialog.js'));
7
- // All three scales, so a display offering this menu at all must hold all three
8
- // in its own `scaleType` enum. `scoreAxisConfigSchemaFields` deliberately does
9
- // not — symlog is widened in by whoever implements it — so a display that spreads
10
- // the shared axis fields unchanged has to opt out with `scaleType: false` the way
11
- // manhattan does, or the radio writes a value its enumeration rejects.
8
+ const SetScoreRulesDialog = lazy(() => import('./SetScoreRulesDialog.js'));
9
+ const SCALE_TYPE_LABELS = {
10
+ linear: 'Linear scale',
11
+ log: 'Log scale',
12
+ symlog: 'Symlog scale (allows zero)',
13
+ };
14
+ // The radio offers exactly what the display's own `scales.y.type` enum admits,
15
+ // read back through `scaleTypeChoices`. Offering a fixed three wrote values an
16
+ // enumeration rejected, which is why Manhattan and the mark display each used to
17
+ // drop the radio by hand.
12
18
  export function makeScaleTypeSubMenu(self) {
13
19
  return {
14
20
  label: 'Scale type',
15
- subMenu: radioItems([
16
- { value: 'linear', label: 'Linear scale' },
17
- { value: 'log', label: 'Log scale' },
18
- { value: 'symlog', label: 'Symlog scale (allows zero)' },
19
- ], self.scaleType, v => {
21
+ subMenu: radioItems(self.scaleTypeChoices.map(value => ({
22
+ value,
23
+ label: SCALE_TYPE_LABELS[value] ?? value,
24
+ })), self.scaleType, v => {
20
25
  self.setScaleType(v);
21
26
  }),
22
27
  };
@@ -51,8 +56,23 @@ export function makeSetMinMaxScoreItem(self) {
51
56
  },
52
57
  };
53
58
  }
54
- // Only offered when a manual bound is set; resets both to the sentinel (same
55
- // path the dialog takes when its fields are cleared) so autoscale resumes.
59
+ // Freezes the axis where it is drawn, so a pan or a zoom no longer moves it:
60
+ // the drawn domain, never the resolved `*Bound` pair, which on an autoscaled
61
+ // track is `undefined` at both ends and would pin nothing. The caller hands
62
+ // the domain in, since each display names its own (`coverageDomain` on the
63
+ // alignments band), and `makeScoreSubMenu` offers the row only while it is
64
+ // known.
65
+ export function makePinCurrentRangeItem(self, domain) {
66
+ return {
67
+ label: 'Pin current min/max',
68
+ onClick: () => {
69
+ self.setMinScore(domain[0]);
70
+ self.setMaxScore(domain[1]);
71
+ },
72
+ };
73
+ }
74
+ // Only offered when a manual bound is set; clears both (same path the dialog
75
+ // takes when its fields are cleared) so autoscale resumes.
56
76
  function makeClearMinMaxScoreItem(self) {
57
77
  return {
58
78
  label: 'Clear manual min/max',
@@ -67,22 +87,28 @@ export function makeCrossHatchItem(self) {
67
87
  self.toggleCrossHatches();
68
88
  });
69
89
  }
70
- // The single Score submenu used by every wiggle-family display. Composition is
71
- // capability-driven: `leadingItems` lets wiggle prepend its Resolution/Summary
72
- // submenus, `trailingItems` appends what belongs after the range controls rather
73
- // than before them (the alignments band's allele-fraction floor); `scaleType` is
74
- // dropped by manhattan (linear-only); `autoscaleOptions` is overridden by
75
- // coverage's reduced + dynamic-σ list.
76
- //
77
- // `autoscale` is the same kind of opt-out as `scaleType`, and exists for the
78
- // same reason: a display whose domain doesn't consult `autoscaleType` must not
79
- // offer radios for it. Manhattan takes plain min/max over the loaded regions and
80
- // applies only the manual bounds, so its Autoscale-type radios wrote the config
81
- // slot and changed nothing on screen — a control that lies is worse than a
82
- // missing one. Opt-out rather than opt-in so a display that grows a domain
83
- // without wiring autoscale keeps the menu it already had.
90
+ function drawsScoreRules(self) {
91
+ return (self.scoreRulesDrawn === true &&
92
+ self.scoreRules !== undefined &&
93
+ self.setScoreRules !== undefined);
94
+ }
95
+ // The count is in the label, as the min/max row carries its bounds: a dashed
96
+ // line across a plot means nothing until the reader knows it was put there.
97
+ export function makeSetScoreRulesItem(self) {
98
+ const count = self.scoreRules.length;
99
+ return {
100
+ label: count > 0 ? `Reference lines (${count})...` : 'Reference lines...',
101
+ icon: HorizontalRuleIcon,
102
+ onClick: () => {
103
+ getDialogHost(self).queueDialog(handleClose => [
104
+ SetScoreRulesDialog,
105
+ { model: self, handleClose },
106
+ ]);
107
+ },
108
+ };
109
+ }
84
110
  export function makeScoreSubMenu(self, opts = {}) {
85
- const { label = 'Score', scaleType = true, autoscale = true, autoscaleOptions, leadingItems = [], trailingItems = [], disabled, disabledHelpText, } = opts;
111
+ const { label = 'Score', autoscaleOptions, domain, leadingItems = [], trailingItems = [], disabled, disabledHelpText, } = opts;
86
112
  return {
87
113
  label,
88
114
  icon: EqualizerIcon,
@@ -90,10 +116,19 @@ export function makeScoreSubMenu(self, opts = {}) {
90
116
  disabledHelpText,
91
117
  subMenu: [
92
118
  ...leadingItems,
93
- ...(scaleType ? [makeScaleTypeSubMenu(self)] : []),
94
- ...(autoscale ? [makeAutoscaleTypeSubMenu(self, autoscaleOptions)] : []),
119
+ ...(self.scaleTypeChoices.length > 1 ? [makeScaleTypeSubMenu(self)] : []),
120
+ ...(self.autoscaleType !== undefined && self.setAutoscale
121
+ ? [
122
+ makeAutoscaleTypeSubMenu({
123
+ autoscaleType: self.autoscaleType,
124
+ setAutoscale: self.setAutoscale,
125
+ }, autoscaleOptions),
126
+ ]
127
+ : []),
95
128
  makeSetMinMaxScoreItem(self),
129
+ ...(domain ? [makePinCurrentRangeItem(self, domain)] : []),
96
130
  ...(self.hasManualScoreBounds ? [makeClearMinMaxScoreItem(self)] : []),
131
+ ...(drawsScoreRules(self) ? [makeSetScoreRulesItem(self)] : []),
97
132
  ...trailingItems,
98
133
  ],
99
134
  };