@jbrowse/wiggle-core 5.0.0-beta.11 → 5.0.0-beta.14

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 (68) hide show
  1. package/README.md +28 -13
  2. package/esm/ResolutionStepper.d.ts +1 -0
  3. package/esm/ResolutionStepper.js +5 -2
  4. package/esm/ScoreAxisWidget/RangeFields.d.ts +5 -0
  5. package/esm/ScoreAxisWidget/RangeFields.js +70 -0
  6. package/esm/ScoreAxisWidget/ReferenceLines.d.ts +10 -0
  7. package/esm/ScoreAxisWidget/ReferenceLines.js +53 -0
  8. package/esm/ScoreAxisWidget/ResetAxisButton.d.ts +7 -0
  9. package/esm/ScoreAxisWidget/ResetAxisButton.js +22 -0
  10. package/esm/ScoreAxisWidget/ScoreAxisHeading.d.ts +5 -0
  11. package/esm/ScoreAxisWidget/ScoreAxisHeading.js +9 -0
  12. package/esm/ScoreAxisWidget/ScoreAxisWidget.d.ts +5 -0
  13. package/esm/ScoreAxisWidget/ScoreAxisWidget.js +69 -0
  14. package/esm/ScoreAxisWidget/Section.d.ts +6 -0
  15. package/esm/ScoreAxisWidget/Section.js +15 -0
  16. package/esm/ScoreAxisWidget/ShareAxisWith.d.ts +5 -0
  17. package/esm/ScoreAxisWidget/ShareAxisWith.js +32 -0
  18. package/esm/ScoreAxisWidget/constants.d.ts +1 -0
  19. package/esm/ScoreAxisWidget/constants.js +1 -0
  20. package/esm/ScoreAxisWidget/index.d.ts +8 -0
  21. package/esm/ScoreAxisWidget/index.js +22 -0
  22. package/esm/ScoreAxisWidget/stateModel.d.ts +30 -0
  23. package/esm/ScoreAxisWidget/stateModel.js +30 -0
  24. package/esm/ScoreAxisWidget/types.d.ts +10 -0
  25. package/esm/ScoreAxisWidget/types.js +1 -0
  26. package/esm/ScoreAxisWidget/writeThrough.d.ts +2 -0
  27. package/esm/ScoreAxisWidget/writeThrough.js +7 -0
  28. package/esm/ScorePlotChrome.d.ts +9 -8
  29. package/esm/ScorePlotChrome.js +16 -8
  30. package/esm/ScorePlotSvgFrame.d.ts +7 -12
  31. package/esm/ScorePlotSvgFrame.js +6 -14
  32. package/esm/ScoreScaleMixin.d.ts +7 -14
  33. package/esm/ScoreScaleMixin.js +7 -21
  34. package/esm/WiggleScoreConfigMixin.d.ts +5 -22
  35. package/esm/WiggleScoreConfigMixin.js +5 -25
  36. package/esm/{ScoreFieldConfigMixin.d.ts → YFieldConfigMixin.d.ts} +11 -15
  37. package/esm/YFieldConfigMixin.js +25 -0
  38. package/esm/autoscale.d.ts +20 -15
  39. package/esm/autoscale.js +37 -34
  40. package/esm/chrome.d.ts +1 -3
  41. package/esm/chrome.js +1 -2
  42. package/esm/dataTypes.d.ts +2 -1
  43. package/esm/index.d.ts +7 -8
  44. package/esm/index.js +5 -6
  45. package/esm/pointSizeMenu.d.ts +12 -24
  46. package/esm/pointSizeMenu.js +9 -20
  47. package/esm/renderingBackendTypes.d.ts +1 -0
  48. package/esm/renderingBackendTypes.js +1 -1
  49. package/esm/scale.d.ts +5 -4
  50. package/esm/scale.js +6 -10
  51. package/esm/scoreMenuItems.d.ts +14 -28
  52. package/esm/scoreMenuItems.js +35 -130
  53. package/esm/valueScaleConfigSchema.d.ts +80 -6
  54. package/esm/valueScaleConfigSchema.js +67 -27
  55. package/esm/yFieldConfigSchemaFields.d.ts +10 -0
  56. package/esm/yFieldConfigSchemaFields.js +8 -0
  57. package/package.json +11 -10
  58. package/esm/AutoscaleGroupDialog.d.ts +0 -7
  59. package/esm/AutoscaleGroupDialog.js +0 -26
  60. package/esm/ScoreFieldConfigMixin.js +0 -25
  61. package/esm/SetMinMaxDialog.d.ts +0 -12
  62. package/esm/SetMinMaxDialog.js +0 -32
  63. package/esm/SetScoreRulesDialog.d.ts +0 -14
  64. package/esm/SetScoreRulesDialog.js +0 -45
  65. package/esm/rowLabelOffset.d.ts +0 -8
  66. package/esm/rowLabelOffset.js +0 -16
  67. package/esm/scoreFieldConfigSchemaFields.d.ts +0 -10
  68. package/esm/scoreFieldConfigSchemaFields.js +0 -8
package/esm/autoscale.js CHANGED
@@ -1,7 +1,7 @@
1
- import { quantileExtent } from '@jbrowse/core/util/quantileExtent';
2
- /** The wiggle packer's arrays as a span, under a summary mode. */
3
- export function datasetSpan({ data, visStart, visEnd }, summaryScoreMode) {
4
- const { low, high } = boundArrays(summaryScoreMode);
1
+ import { fenceOutliers, quantileExtent, } from '@jbrowse/core/util/quantileExtent';
2
+ /** The wiggle packer's arrays as a span, under an aggregate and an extent. */
3
+ export function datasetSpan({ data, visStart, visEnd }, aggregate, extent) {
4
+ const { low, high } = boundArrays(aggregate, extent);
5
5
  return {
6
6
  count: data.numFeatures,
7
7
  starts: data.featurePositions,
@@ -17,13 +17,13 @@ export function datasetSpan({ data, visStart, visEnd }, summaryScoreMode) {
17
17
  }
18
18
  /**
19
19
  * #api
20
- * Per-feature scalar score array for a summary mode: the min/max summary array
20
+ * Per-feature scalar score array for an aggregate: the min/max summary array
21
21
  * for `'min'`/`'max'`, otherwise the average score.
22
22
  */
23
- export function getEffectiveScores(data, summaryScoreMode) {
24
- return summaryScoreMode === 'min'
23
+ export function getEffectiveScores(data, aggregate) {
24
+ return aggregate === 'min'
25
25
  ? data.featureMinScores
26
- : summaryScoreMode === 'max'
26
+ : aggregate === 'max'
27
27
  ? data.featureMaxScores
28
28
  : data.featureScores;
29
29
  }
@@ -31,19 +31,15 @@ export function getEffectiveScores(data, summaryScoreMode) {
31
31
  function overlaps(fStart, fEnd, visStart, visEnd) {
32
32
  return fEnd > visStart && fStart < visEnd;
33
33
  }
34
- // Which per-feature array each end of the domain comes from. Whiskers spreads
35
- // the two ends across the min/max summary arrays; every other mode draws both
36
- // from a single scalar. One table because the extent and the clipped bound have
37
- // to read the same arrays, or a domain clips its own data.
38
- function boundArrays(summaryScoreMode) {
39
- const useWhiskers = summaryScoreMode === 'whiskers';
34
+ // Which per-feature array each end of the domain comes from. A min-max extent
35
+ // spreads the two ends across the min/max summary arrays; without one both come
36
+ // from the aggregate's single array. One table because the data's span and the
37
+ // clipped bound have to read the same arrays, or a domain clips its own data.
38
+ function boundArrays(aggregate, extent) {
39
+ const minMax = extent === 'min-max';
40
40
  return {
41
- low: (data) => useWhiskers
42
- ? data.featureMinScores
43
- : getEffectiveScores(data, summaryScoreMode),
44
- high: (data) => useWhiskers
45
- ? data.featureMaxScores
46
- : getEffectiveScores(data, summaryScoreMode),
41
+ low: (data) => minMax ? data.featureMinScores : getEffectiveScores(data, aggregate),
42
+ high: (data) => minMax ? data.featureMaxScores : getEffectiveScores(data, aggregate),
47
43
  };
48
44
  }
49
45
  // First index whose instance STARTS at or after `bp`. `starts` is sorted by
@@ -122,18 +118,19 @@ export function computeSpanStats(spans) {
122
118
  : undefined;
123
119
  }
124
120
  /** `computeSpanStats` over the wiggle packer's datasets. */
125
- export function computeScoreStats(summaryScoreMode, datasets) {
126
- return computeSpanStats(datasets.map(d => datasetSpan(d, summaryScoreMode)));
121
+ export function computeScoreStats(aggregate, datasets, extent) {
122
+ return computeSpanStats(datasets.map(d => datasetSpan(d, aggregate, extent)));
127
123
  }
128
124
  /**
129
125
  * #api
130
126
  * The domain the visible instances autoscale to: at a `quantile` of 1 their
131
- * extremes, `stats`; below it `quantileExtent`'s ends, the bottom read off
132
- * the `low`s and the top off the `high`s less the zeros where any is
133
- * positive, so whiskers open to their spread, a sparse window's empty bins
134
- * lower no top, and a window of nothing above 0 keeps the top it has.
127
+ * extremes, `stats`; below it those extremes fenced by `quantileExtent`'s
128
+ * ends (`fenceOutliers`), the bottom read off the `low`s and the top off the
129
+ * `high`s less the zeros where any is positive, so whiskers open to their
130
+ * spread, a sparse window's empty bins lower no top, and a window of nothing
131
+ * above 0 keeps the top it has.
135
132
  */
136
- export function autoscaleDomainFromSpans({ stats, quantile, spans, }) {
133
+ export function autoscaleDomainFromSpans({ stats, quantile, zero, spans, }) {
137
134
  if (quantile >= 1) {
138
135
  return [stats.scoreMin, stats.scoreMax];
139
136
  }
@@ -153,25 +150,31 @@ export function autoscaleDomainFromSpans({ stats, quantile, spans, }) {
153
150
  const tops = highs.some(v => v > 0) ? highs.filter(v => v !== 0) : highs;
154
151
  const min = quantileExtent(lows, lows.length, quantile)[0];
155
152
  const max = quantileExtent(tops, tops.length, quantile)[1];
156
- return [Number.isFinite(min) ? min : 0, Number.isFinite(max) ? max : 0];
153
+ return fenceOutliers({
154
+ extremes: [stats.scoreMin, stats.scoreMax],
155
+ quantiles: [Number.isFinite(min) ? min : 0, Number.isFinite(max) ? max : 0],
156
+ zero,
157
+ });
157
158
  }
158
159
  /** `autoscaleDomainFromSpans` over the wiggle packer's datasets. */
159
- export function autoscaleDomainFromStats({ stats, quantile, summaryScoreMode, visibleEntries, }) {
160
+ export function autoscaleDomainFromStats({ stats, quantile, zero, aggregate, extent, visibleEntries, }) {
160
161
  return autoscaleDomainFromSpans({
161
162
  stats,
162
163
  quantile,
163
- spans: visibleEntries.map(d => datasetSpan(d, summaryScoreMode)),
164
+ zero,
165
+ spans: visibleEntries.map(d => datasetSpan(d, aggregate, extent)),
164
166
  });
165
167
  }
166
168
  /**
167
169
  * #api
168
170
  * The score domain of the visible feature arrays, following `quantile` as
169
- * `scales.y.domainQuantile` says.
171
+ * `scales.y.domainQuantile` says, its outliers fenced for an axis that
172
+ * reaches 0 under `zero`.
170
173
  */
171
- export function computeAutoscaleDomain(quantile, summaryScoreMode, visibleEntries) {
172
- const spans = visibleEntries.map(d => datasetSpan(d, summaryScoreMode));
174
+ export function computeAutoscaleDomain(quantile, aggregate, visibleEntries, zero, extent = 'none') {
175
+ const spans = visibleEntries.map(d => datasetSpan(d, aggregate, extent));
173
176
  const stats = computeSpanStats(spans);
174
177
  return stats
175
- ? autoscaleDomainFromSpans({ stats, quantile, spans })
178
+ ? autoscaleDomainFromSpans({ stats, quantile, zero, spans })
176
179
  : undefined;
177
180
  }
package/esm/chrome.d.ts CHANGED
@@ -1,5 +1,3 @@
1
1
  export { AxisGutter, CrossHatchLines, CrossHatches, ScoreDomainCaption, ScoreRuleLines, ScoreRules, YScaleBar, YScaleBarOverlay, } from '@jbrowse/display-ui';
2
2
  export { makeResolutionSubMenuItem } from './ResolutionStepper.tsx';
3
- export { makePointSizeSubMenu, pointSizeAccess } from './pointSizeMenu.tsx';
4
- export type { PointSizeAccess } from './pointSizeMenu.tsx';
5
- export { default as SetMinMaxDialog } from './SetMinMaxDialog.tsx';
3
+ export { makeMarkSizeSubMenu } from './pointSizeMenu.tsx';
package/esm/chrome.js CHANGED
@@ -3,5 +3,4 @@
3
3
  // an adapter or an RPC method never does.
4
4
  export { AxisGutter, CrossHatchLines, CrossHatches, ScoreDomainCaption, ScoreRuleLines, ScoreRules, YScaleBar, YScaleBarOverlay, } from '@jbrowse/display-ui';
5
5
  export { makeResolutionSubMenuItem } from './ResolutionStepper.js';
6
- export { makePointSizeSubMenu, pointSizeAccess } from './pointSizeMenu.js';
7
- export { default as SetMinMaxDialog } from './SetMinMaxDialog.js';
6
+ export { makeMarkSizeSubMenu } from './pointSizeMenu.js';
@@ -2,7 +2,6 @@ import type { ZoomRange } from '@jbrowse/core/data_adapters/BaseAdapter/zoomRang
2
2
  export interface SourceInfo {
3
3
  name: string;
4
4
  color?: string;
5
- labelColor?: string;
6
5
  label?: string;
7
6
  group?: string;
8
7
  baseUri?: string;
@@ -21,4 +20,6 @@ export interface WiggleDataResult {
21
20
  zoomRange?: ZoomRange;
22
21
  /** The bounds the adapter's values lie in by definition (`getValueDomain`). */
23
22
  valueDomain?: [number, number];
23
+ /** What the adapter's source listing dropped or could not match. */
24
+ warnings?: string[];
24
25
  }
package/esm/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { retiredAxisSpellings, scalesSchema, valueScaleSchema, } from './valueScaleConfigSchema.ts';
2
- export type { ScalesConfigSchema, ValueScaleConfigSchema, ValueScaleOptions, } from './valueScaleConfigSchema.ts';
1
+ export { retiredAxisSpellings, retiredScaleSpellings, scalesSchema, valueScaleOf, valueScaleSchema, } from './valueScaleConfigSchema.ts';
2
+ export type { ScalesConfigSchema, ValueScaleConfigSchema, ValueScaleOptions, ValueScaleRuleConfig, } 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';
@@ -11,22 +11,21 @@ export { DEFAULT_RULE_COLOR, SCORE_CAPTION_HEIGHT, YSCALEBAR_LABEL_OFFSET, } fro
11
11
  export { AXIS_GUTTER_WIDTH_PX, axisPlotBox, clampStrokeInsideAxis, scoreToAxisY, } from '@jbrowse/display-ui/yScaleTicks';
12
12
  export type { ValueScale, ValueScaleRule, YAxis, YScaleTicks, } from '@jbrowse/display-ui';
13
13
  export { computeYTicks } from './computeYTicks.ts';
14
- export { rowLabelOffset } from './rowLabelOffset.ts';
15
14
  export { resolveRenderState } from './resolveRenderState.ts';
16
15
  export { visibleStatsDomain, visibleStatsRange } from './visibleStatsDomain.ts';
17
16
  export type { SettledBlocksView, VisibleEntry, VisibleStatsDomainSpec, VisibleStatsRangeSpec, } from './visibleStatsDomain.ts';
18
17
  export { scoreRuleMarks, widenRangeToRules } from './scoreRuleMarks.ts';
19
18
  export type { ScoreRuleMark } from './scoreRuleMarks.ts';
20
19
  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';
20
+ export { COVERAGE_AXIS_LABEL, SCORE_RANGE_LABEL, Y_AXIS_LABEL, makeScoreAxisMenuItem, } from './scoreMenuItems.ts';
21
+ export type { ScoreAxisMenuItemOptions, ScoreRulesModel, ScoreScaleModel, } from './scoreMenuItems.ts';
23
22
  export { ScoreAxisMixin } from './ScoreAxisMixin.ts';
24
23
  export { ScoreScaleMixin } from './ScoreScaleMixin.ts';
25
24
  export type { ScoreScaleHost } from './ScoreScaleMixin.ts';
26
- export { WiggleScoreConfigMixin, wiggleScoreConfigExtraSlots, } from './WiggleScoreConfigMixin.ts';
25
+ export { WiggleScoreConfigMixin } from './WiggleScoreConfigMixin.ts';
27
26
  export type { WiggleScoreConfigHost } from './WiggleScoreConfigMixin.ts';
28
- export { ScoreFieldConfigMixin } from './ScoreFieldConfigMixin.ts';
29
- export { DEFAULT_SCORE_FIELD, scoreFieldConfigSchemaFields, } from './scoreFieldConfigSchemaFields.ts';
27
+ export { YFieldConfigMixin } from './YFieldConfigMixin.ts';
28
+ export { DEFAULT_SCORE_FIELD, yFieldConfigSchemaFields, } from './yFieldConfigSchemaFields.ts';
30
29
  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';
31
30
  export type { SourceRenderData, WiggleGPURenderState, WiggleRenderingBackend, WiggleRenderingType, } from './renderingBackendTypes.ts';
32
31
  export type { SourceInfo, WiggleDataResult, WiggleFeatureArrays, WiggleSourceData, } from './dataTypes.ts';
package/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { retiredAxisSpellings, scalesSchema, valueScaleSchema, } from './valueScaleConfigSchema.js';
1
+ export { retiredAxisSpellings, retiredScaleSpellings, scalesSchema, valueScaleOf, valueScaleSchema, } from './valueScaleConfigSchema.js';
2
2
  export { getNiceDomain, getNiceScale, getScale } from './scale.js';
3
3
  export { toP } from './formatNumber.js';
4
4
  export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormalizer, resolveSymlogConstant, } from './normalize.js';
@@ -11,17 +11,16 @@ export { axisDrawn } from '@jbrowse/display-ui/axisPlacement';
11
11
  export { DEFAULT_RULE_COLOR, SCORE_CAPTION_HEIGHT, YSCALEBAR_LABEL_OFFSET, } from '@jbrowse/display-ui/yAxisConstants';
12
12
  export { AXIS_GUTTER_WIDTH_PX, axisPlotBox, clampStrokeInsideAxis, scoreToAxisY, } from '@jbrowse/display-ui/yScaleTicks';
13
13
  export { computeYTicks } from './computeYTicks.js';
14
- export { rowLabelOffset } from './rowLabelOffset.js';
15
14
  export { resolveRenderState } from './resolveRenderState.js';
16
15
  export { visibleStatsDomain, visibleStatsRange } from './visibleStatsDomain.js';
17
16
  export { scoreRuleMarks, widenRangeToRules } from './scoreRuleMarks.js';
18
17
  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';
18
+ export { COVERAGE_AXIS_LABEL, SCORE_RANGE_LABEL, Y_AXIS_LABEL, makeScoreAxisMenuItem, } from './scoreMenuItems.js';
20
19
  export { ScoreAxisMixin } from './ScoreAxisMixin.js';
21
20
  export { ScoreScaleMixin } from './ScoreScaleMixin.js';
22
- export { WiggleScoreConfigMixin, wiggleScoreConfigExtraSlots, } from './WiggleScoreConfigMixin.js';
23
- export { ScoreFieldConfigMixin } from './ScoreFieldConfigMixin.js';
24
- export { DEFAULT_SCORE_FIELD, scoreFieldConfigSchemaFields, } from './scoreFieldConfigSchemaFields.js';
21
+ export { WiggleScoreConfigMixin } from './WiggleScoreConfigMixin.js';
22
+ export { YFieldConfigMixin } from './YFieldConfigMixin.js';
23
+ export { DEFAULT_SCORE_FIELD, yFieldConfigSchemaFields, } from './yFieldConfigSchemaFields.js';
25
24
  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';
26
25
  export {} from './displayModel.js';
27
26
  export { collectWiggleTransferables } from './transferables.js';
@@ -1,32 +1,20 @@
1
- import type { ConfigModelForFields } from '@jbrowse/core/configuration';
2
1
  import type { MenuItem } from '@jbrowse/core/ui';
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;
2
+ import type { ElementType } from 'react';
23
3
  /**
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.
4
+ * A top-level submenu holding a mark's size slider, or nothing where the plot
5
+ * draws no such mark, so every score plot's menu resets and clamps alike.
26
6
  * Top-level rather than under Score because the size describes the mark, not
27
7
  * the axis.
28
8
  */
29
- export declare function makePointSizeSubMenu({ label, applies, value, defaultValue, set, }: PointSizeAccess & {
9
+ export declare function makeMarkSizeSubMenu({ label, title, icon, applies, value, isDefault, set, min, max, step, }: {
30
10
  label: string;
11
+ title?: string;
12
+ icon?: ElementType;
31
13
  applies: boolean;
14
+ value: () => number;
15
+ isDefault: boolean;
16
+ set: (n?: number) => void;
17
+ min?: number;
18
+ max?: number;
19
+ step?: number;
32
20
  }): MenuItem[];
@@ -1,37 +1,26 @@
1
- import { getSlotDefinition } from '@jbrowse/core/configuration';
2
1
  import { makeSizeMenu } from '@jbrowse/core/ui';
3
2
  import ScatterPlotIcon from '@mui/icons-material/ScatterPlot';
4
3
  /**
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);
14
- },
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.
4
+ * A top-level submenu holding a mark's size slider, or nothing where the plot
5
+ * draws no such mark, so every score plot's menu resets and clamps alike.
20
6
  * Top-level rather than under Score because the size describes the mark, not
21
7
  * the axis.
22
8
  */
23
- export function makePointSizeSubMenu({ label, applies, value, defaultValue, set, }) {
9
+ export function makeMarkSizeSubMenu({ label, title = 'Point size', icon = ScatterPlotIcon, applies, value, isDefault, set, min, max, step, }) {
24
10
  return applies
25
11
  ? [
26
12
  {
27
13
  label,
28
- icon: ScatterPlotIcon,
14
+ icon,
29
15
  subMenu: [
30
16
  makeSizeMenu({
31
17
  label,
32
- title: 'Point size',
18
+ title,
19
+ min,
20
+ max,
21
+ step,
33
22
  getValue: value,
34
- isDefault: value() === defaultValue,
23
+ isDefault,
35
24
  onChange: set,
36
25
  onReset: () => {
37
26
  set();
@@ -41,6 +41,7 @@ export interface SourceRenderData {
41
41
  colorsAbgr?: Uint32Array;
42
42
  negColor?: [number, number, number];
43
43
  gapLimitBp?: number;
44
+ gapScore?: number;
44
45
  band?: {
45
46
  minScores: Float32Array;
46
47
  };
@@ -27,6 +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
30
+ // The most cuts a threshold color parts a plot at: the shader's uniform
31
31
  // block holds this many.
32
32
  export const MAX_WIGGLE_CUTS = GENERATED_MAX_WIGGLE_CUTS;
package/esm/scale.d.ts CHANGED
@@ -37,10 +37,11 @@ export declare function getScale({ domain, range, scaleType, symlogConstant, nic
37
37
  /**
38
38
  * #api
39
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.
40
+ * domain to 0 (`scales.y.zero`, ADR-182); a log domain has no 0, so a min at
41
+ * or below it floors to a positive value and a positive min stays where the
42
+ * data put it. An end given an explicit `bounds` value keeps that value
43
+ * exactly — only an autoscaled end is rounded. A log scale's floor still
44
+ * outranks a bound it cannot hold, which the `log-floor` rule reports.
44
45
  *
45
46
  * The result never descends and never collapses: a bound that would put `min`
46
47
  * above `max` widens the other end instead, and one value in view widens
package/esm/scale.js CHANGED
@@ -65,10 +65,11 @@ export function getScale({ domain, range, scaleType, symlogConstant, nice = true
65
65
  /**
66
66
  * #api
67
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.
68
+ * domain to 0 (`scales.y.zero`, ADR-182); a log domain has no 0, so a min at
69
+ * or below it floors to a positive value and a positive min stays where the
70
+ * data put it. An end given an explicit `bounds` value keeps that value
71
+ * exactly — only an autoscaled end is rounded. A log scale's floor still
72
+ * outranks a bound it cannot hold, which the `log-floor` rule reports.
72
73
  *
73
74
  * The result never descends and never collapses: a bound that would put `min`
74
75
  * above `max` widens the other end instead, and one value in view widens
@@ -92,11 +93,6 @@ export function getNiceDomain({ scaleType, domain, bounds, zero, }) {
92
93
  min = 0;
93
94
  }
94
95
  }
95
- if (scaleType === 'log') {
96
- if (min >= 0 && max > 1) {
97
- min = 1;
98
- }
99
- }
100
96
  if (minScore !== undefined) {
101
97
  min = minScore;
102
98
  }
@@ -147,7 +143,7 @@ export function getNiceDomain({ scaleType, domain, bounds, zero, }) {
147
143
  }
148
144
  }
149
145
  // Rounding is for an autoscaled end, whose only meaning is "roughly the
150
- // data's extent". A bound the user typed into Set min/max score means itself,
146
+ // data's extent". A bound the user typed into the Y axis panel means itself,
151
147
  // and the menu row goes on displaying it, so it is taken as given.
152
148
  //
153
149
  // `min`/`max` rather than `minScore`/`maxScore`: the log guards above may
@@ -1,5 +1,4 @@
1
- import type { AutoscalePeer } from './autoscaleGroup.ts';
2
- import type { CheckboxMenuItem, MenuItem } from '@jbrowse/core/ui';
1
+ import type { NormalMenuItem } from '@jbrowse/core/ui';
3
2
  import type { ValueScaleRule } from '@jbrowse/display-ui';
4
3
  import type { IStateTreeNode } from '@jbrowse/mobx-state-tree';
5
4
  export interface ScoreScaleModel extends IStateTreeNode {
@@ -12,6 +11,7 @@ export interface ScoreScaleModel extends IStateTreeNode {
12
11
  minScoreBound: number | undefined;
13
12
  maxScoreBound: number | undefined;
14
13
  hasManualScoreBounds: boolean;
14
+ autoscaleRange: [number, number] | undefined;
15
15
  autoscaledDomain: [number, number] | undefined;
16
16
  setScaleType: (v: string) => void;
17
17
  setScaleZero: (zero: boolean) => void;
@@ -24,33 +24,19 @@ export interface ScoreRulesModel {
24
24
  scoreRules: ValueScaleRule[];
25
25
  setScoreRules: (rules: ValueScaleRule[]) => void;
26
26
  }
27
- export declare function makeScaleTypeSubMenu(self: {
28
- scaleType: string;
29
- setScaleType: (v: string) => void;
30
- }): MenuItem;
31
- export declare const CLIP_OUTLIERS_LABEL = "Clip outliers";
32
- export declare function makeClipOutliersItem(self: {
33
- domainQuantile: number;
34
- clipQuantile: number;
35
- setDomainQuantile: (quantile: number) => void;
36
- }): CheckboxMenuItem;
37
- export declare const AXIS_ZERO_LABEL = "Start axis at 0";
38
- export declare function makeAxisZeroItem(self: {
39
- scaleZero: boolean;
40
- setScaleZero: (zero: boolean) => void;
41
- }): CheckboxMenuItem;
42
- export declare function makeSetMinMaxScoreItem(self: ScoreScaleModel): MenuItem;
43
- export declare function makeCrossHatchItem(self: {
44
- grid: boolean;
45
- setGrid: (grid: boolean) => void;
46
- }): MenuItem;
47
- export interface ScoreSubMenuOptions {
27
+ export declare const Y_AXIS_LABEL = "Y axis";
28
+ export declare const COVERAGE_AXIS_LABEL = "Coverage axis";
29
+ export declare const SCORE_RANGE_LABEL = "Score range";
30
+ export interface ScoreAxisMenuItemOptions {
48
31
  label?: string;
49
- leadingItems?: MenuItem[];
50
- trailingItems?: MenuItem[];
51
32
  disabled?: boolean;
52
33
  disabledHelpText?: string;
53
34
  }
54
- export declare function makeAutoscaleGroupItem(self: IStateTreeNode & AutoscalePeer): MenuItem;
55
- export declare function makeSetScoreRulesItem(self: IStateTreeNode & ScoreRulesModel): MenuItem;
56
- export declare function makeScoreSubMenu(self: ScoreScaleModel & Partial<ScoreRulesModel> & Partial<AutoscalePeer>, opts?: ScoreSubMenuOptions): MenuItem;
35
+ /**
36
+ * The one track-menu row for a value scale. It opens the drawer widget that
37
+ * edits `scales.y` live — scale type, range, 0, outlier clipping, the axis a
38
+ * group shares, grid and reference lines — so the track redraws beside it.
39
+ */
40
+ export declare function makeScoreAxisMenuItem(self: ScoreScaleModel & {
41
+ id: string;
42
+ }, opts?: ScoreAxisMenuItemOptions): NormalMenuItem;
@@ -1,137 +1,42 @@
1
- import { lazy } from 'react';
2
- import { checkboxItem, radioItems, toggleItem, } from '@jbrowse/core/ui/menuItems';
3
- import { getDialogHost } from '@jbrowse/core/util';
1
+ import { getSession, isSessionModelWithWidgets } from '@jbrowse/core/util';
4
2
  import EqualizerIcon from '@mui/icons-material/Equalizer';
5
- import { autoscaleGroupMembers, autoscalePeers } from './autoscaleGroup.js';
6
- import { VALUE_SCALE_TYPES } from './valueScaleConfigSchema.js';
7
- const AutoscaleGroupDialog = lazy(() => import('./AutoscaleGroupDialog.js'));
8
- const SetMinMaxDialog = lazy(() => import('./SetMinMaxDialog.js'));
9
- const SetScoreRulesDialog = lazy(() => import('./SetScoreRulesDialog.js'));
10
- const SCALE_TYPE_LABELS = {
11
- linear: 'Linear scale',
12
- log: 'Log scale',
13
- symlog: 'Symlog scale (allows zero)',
14
- };
15
- export function makeScaleTypeSubMenu(self) {
3
+ import { SCORE_AXIS_WIDGET } from './ScoreAxisWidget/constants.js';
4
+ // Quoted by the docs' click paths, so literal strings.
5
+ export const Y_AXIS_LABEL = 'Y axis';
6
+ export const COVERAGE_AXIS_LABEL = 'Coverage axis';
7
+ export const SCORE_RANGE_LABEL = 'Score range';
8
+ // The caption carries only what the plot cannot show: a pinned end, `auto`
9
+ // for the other, and a scale that isn't linear. The resolved pair would
10
+ // caption every GC content track "(0 – 1)" off its default domain.
11
+ function caption(self) {
12
+ const parts = [
13
+ ...(self.hasManualScoreBounds
14
+ ? [`${self.manualMinScore ?? 'auto'} – ${self.manualMaxScore ?? 'auto'}`]
15
+ : []),
16
+ ...(self.scaleType === 'linear' ? [] : [self.scaleType]),
17
+ ];
18
+ return parts.length ? ` (${parts.join(', ')})` : '';
19
+ }
20
+ /**
21
+ * The one track-menu row for a value scale. It opens the drawer widget that
22
+ * edits `scales.y` live — scale type, range, 0, outlier clipping, the axis a
23
+ * group shares, grid and reference lines — so the track redraws beside it.
24
+ */
25
+ export function makeScoreAxisMenuItem(self, opts = {}) {
26
+ const { label = Y_AXIS_LABEL, disabled, disabledHelpText } = opts;
16
27
  return {
17
- label: 'Scale type',
18
- subMenu: radioItems(VALUE_SCALE_TYPES.map(value => ({
19
- value,
20
- label: SCALE_TYPE_LABELS[value],
21
- })), self.scaleType, v => {
22
- self.setScaleType(v);
23
- }),
24
- };
25
- }
26
- // Quoted by the docs' click paths, so one literal string.
27
- export const CLIP_OUTLIERS_LABEL = 'Clip outliers';
28
- // One checkbox rather than a radio over modes: what a reader decides is whether
29
- // a spike may take the axis, and the quantile it clips at is the config's.
30
- export function makeClipOutliersItem(self) {
31
- const clipsAt = self.domainQuantile < 1 ? self.domainQuantile : self.clipQuantile;
32
- const percent = Math.round(clipsAt * 100);
33
- return toggleItem(CLIP_OUTLIERS_LABEL, self.domainQuantile < 1, on => {
34
- self.setDomainQuantile(on ? self.clipQuantile : 1);
35
- }, {
36
- helpText: `An unpinned end follows the ${percent}th percentile of each sign rather than the extremes, so one spike no longer flattens the rest.`,
37
- });
38
- }
39
- // Quoted by the docs' click paths, so one literal string.
40
- export const AXIS_ZERO_LABEL = 'Start axis at 0';
41
- export function makeAxisZeroItem(self) {
42
- return toggleItem(AXIS_ZERO_LABEL, self.scaleZero, zero => {
43
- self.setScaleZero(zero);
44
- }, {
45
- helpText: 'A linear or symlog axis reaches 0 whatever the values in view span. Off, it spans those values alone.',
46
- });
47
- }
48
- // The label shows the PINNED pair, `auto` for an end nobody pinned: the
49
- // resolved pair captioned every GC content track "(0 – 1)" off its default
50
- // domain. "Use current range" copies `autoscaledDomain`, undefined while the
51
- // alignments density tier's features per bin stand in for depth.
52
- export function makeSetMinMaxScoreItem(self) {
53
- const { manualMinScore, manualMaxScore, autoscaledDomain: domain } = self;
54
- return {
55
- label: self.hasManualScoreBounds
56
- ? `Set min/max score (${manualMinScore ?? 'auto'} – ${manualMaxScore ?? 'auto'})...`
57
- : 'Set min/max score...',
58
- onClick: () => {
59
- getDialogHost(self).queueDialog(handleClose => [
60
- SetMinMaxDialog,
61
- { model: self, domain, handleClose },
62
- ]);
63
- },
64
- };
65
- }
66
- export function makeCrossHatchItem(self) {
67
- return checkboxItem('Show cross hatches', self.grid, () => {
68
- self.setGrid(!self.grid);
69
- });
70
- }
71
- // The count of the other tracks in the group is in the label, as the min/max
72
- // row carries its bounds: an axis that moves when another track pans is
73
- // something the reader has to be able to find the cause of.
74
- export function makeAutoscaleGroupItem(self) {
75
- const { autoscaleGroup } = self;
76
- const others = autoscaleGroup === undefined
77
- ? 0
78
- : autoscaleGroupMembers(self, autoscaleGroup).length - 1;
79
- return {
80
- label: others > 0
81
- ? `Autoscale with other tracks (${others})...`
82
- : 'Autoscale with other tracks...',
83
- onClick: () => {
84
- getDialogHost(self).queueDialog(handleClose => [
85
- AutoscaleGroupDialog,
86
- { model: self, handleClose },
87
- ]);
88
- },
89
- };
90
- }
91
- // Offered once the view holds another track with a value axis to share.
92
- function autoscalesInGroups(self) {
93
- return self.setAutoscaleGroup !== undefined && autoscalePeers(self).length > 0;
94
- }
95
- function drawsScoreRules(self) {
96
- return (self.scoreRulesDrawn === true &&
97
- self.scoreRules !== undefined &&
98
- self.setScoreRules !== undefined);
99
- }
100
- // A density plot maps its score to colour and rules no band, so its domain
101
- // spans the values whatever `zero` says; the row is offered with the axis.
102
- function rulesABand(self) {
103
- return self.scoreRulesDrawn === true;
104
- }
105
- // The count is in the label, as the min/max row carries its bounds: a dashed
106
- // line across a plot means nothing until the reader knows it was put there.
107
- export function makeSetScoreRulesItem(self) {
108
- const count = self.scoreRules.length;
109
- return {
110
- label: count > 0 ? `Reference lines (${count})...` : 'Reference lines...',
111
- onClick: () => {
112
- getDialogHost(self).queueDialog(handleClose => [
113
- SetScoreRulesDialog,
114
- { model: self, handleClose },
115
- ]);
116
- },
117
- };
118
- }
119
- export function makeScoreSubMenu(self, opts = {}) {
120
- const { label = 'Score', leadingItems = [], trailingItems = [], disabled, disabledHelpText, } = opts;
121
- return {
122
- label,
28
+ label: `${label}${caption(self)}...`,
123
29
  icon: EqualizerIcon,
124
30
  disabled,
125
31
  disabledHelpText,
126
- subMenu: [
127
- ...leadingItems,
128
- makeScaleTypeSubMenu(self),
129
- makeClipOutliersItem(self),
130
- ...(rulesABand(self) ? [makeAxisZeroItem(self)] : []),
131
- makeSetMinMaxScoreItem(self),
132
- ...(autoscalesInGroups(self) ? [makeAutoscaleGroupItem(self)] : []),
133
- ...(drawsScoreRules(self) ? [makeSetScoreRulesItem(self)] : []),
134
- ...trailingItems,
135
- ],
32
+ onClick: () => {
33
+ const session = getSession(self);
34
+ if (isSessionModelWithWidgets(session)) {
35
+ session.openWidget(SCORE_AXIS_WIDGET, 'scoreAxis', {
36
+ display: self.id,
37
+ label,
38
+ });
39
+ }
40
+ },
136
41
  };
137
42
  }