@jbrowse/wiggle-core 5.0.0-beta.3 → 5.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/ScoreScaleMixin.d.ts +35 -0
- package/esm/ScoreScaleMixin.js +61 -1
- package/esm/computeYTicks.d.ts +1 -1
- package/esm/computeYTicks.js +1 -2
- package/esm/constants.d.ts +1 -2
- package/esm/constants.js +1 -10
- package/esm/displayModel.d.ts +1 -1
- package/esm/index.d.ts +2 -8
- package/esm/index.js +4 -7
- package/esm/pointSizeMenu.d.ts +8 -7
- package/esm/pointSizeMenu.js +7 -8
- package/esm/scoreRuleMarks.d.ts +2 -3
- package/esm/scoreRuleMarks.js +1 -1
- package/package.json +5 -4
- package/esm/CrossHatches.d.ts +0 -11
- package/esm/CrossHatches.js +0 -32
- package/esm/ScoreRules.d.ts +0 -11
- package/esm/ScoreRules.js +0 -37
- package/esm/YScaleBar.d.ts +0 -6
- package/esm/YScaleBar.js +0 -46
- package/esm/YScaleBarOverlay.d.ts +0 -6
- package/esm/YScaleBarOverlay.js +0 -24
- package/esm/YScaleGutter.d.ts +0 -27
- package/esm/YScaleGutter.js +0 -31
- package/esm/yScaleTicks.d.ts +0 -59
- package/esm/yScaleTicks.js +0 -59
package/esm/ScoreScaleMixin.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ScoreAxisConfigModel } from './scoreAxisConfigSchemaFields.ts';
|
|
2
|
+
import type { ValueScale, YAxis } from '@jbrowse/display-ui';
|
|
2
3
|
/**
|
|
3
4
|
* The whole of what `ScoreScaleMixin` needs a composing display to be. Exported
|
|
4
5
|
* because it is the mixin's contract and `ScoreScaleMixin.test.ts` pins it:
|
|
@@ -34,11 +35,29 @@ export interface ScoreScaleHost {
|
|
|
34
35
|
* means "autoscale this end". Every consumer that computes a domain reads the
|
|
35
36
|
* `*Bound` pair.
|
|
36
37
|
*
|
|
38
|
+
* A display that declares its value scale elsewhere answers
|
|
39
|
+
* `declaredValueScale`, and then the scale type and the pinned bounds come
|
|
40
|
+
* from the declaration rather than from `scaleType`/`minScore`/`maxScore`.
|
|
41
|
+
* Its setters are the display's to override so the edit lands on the same
|
|
42
|
+
* declaration — one owner, whichever it is.
|
|
43
|
+
*
|
|
37
44
|
* Whether a bound is *configured* is a third question, and `hasManualScoreBounds`
|
|
38
45
|
* is the only getter that answers it — the resolved pair cannot, since
|
|
39
46
|
* `defaultScoreDomain` is exactly the hook that turns an unset end into a number.
|
|
40
47
|
*/
|
|
41
48
|
export declare function ScoreScaleMixin(): import("@jbrowse/mobx-state-tree").IModelType<{}, {
|
|
49
|
+
/**
|
|
50
|
+
* #getter
|
|
51
|
+
* Overridable hook: a value scale the display declares somewhere other
|
|
52
|
+
* than these slots — the mark display's `encoding.y`. Where it answers,
|
|
53
|
+
* it is the owner and the slots below stand in only for the ends it
|
|
54
|
+
* leaves open, so a scale is read from one place whichever place that
|
|
55
|
+
* is. Default none, which is every display whose axis IS these slots.
|
|
56
|
+
*/
|
|
57
|
+
readonly declaredValueScale: {
|
|
58
|
+
scaleType?: string;
|
|
59
|
+
domain?: [number | undefined, number | undefined];
|
|
60
|
+
} | undefined;
|
|
42
61
|
/**
|
|
43
62
|
* #getter
|
|
44
63
|
*/
|
|
@@ -112,6 +131,22 @@ export declare function ScoreScaleMixin(): import("@jbrowse/mobx-state-tree").IM
|
|
|
112
131
|
* there is a row that does nothing and never goes away.
|
|
113
132
|
*/
|
|
114
133
|
readonly hasManualScoreBounds: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* #getter
|
|
136
|
+
* Overridable hook (default none): the scales this display draws its y
|
|
137
|
+
* through. A display that answers it gets an axis per band of each,
|
|
138
|
+
* with its cross-hatches, placed by `DisplayChrome` and
|
|
139
|
+
* `renderDisplaySvg`, and the ticks derived below.
|
|
140
|
+
*/
|
|
141
|
+
readonly valueScales: ValueScale[];
|
|
142
|
+
} & {
|
|
143
|
+
/**
|
|
144
|
+
* #getter
|
|
145
|
+
* The axes, one per declared scale whose domain resolved: where each
|
|
146
|
+
* tick lands in the band's own pixel space, through `computeYTicks`
|
|
147
|
+
* unless the scale brought its own ladder.
|
|
148
|
+
*/
|
|
149
|
+
readonly axes: YAxis[];
|
|
115
150
|
} & {
|
|
116
151
|
/**
|
|
117
152
|
* #action
|
package/esm/ScoreScaleMixin.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getConf, setConf } from '@jbrowse/core/configuration';
|
|
2
2
|
import { types } from '@jbrowse/mobx-state-tree';
|
|
3
|
+
import { computeYTicks } from './computeYTicks.js';
|
|
3
4
|
// The mixin composes onto a display that declares this, not the other way
|
|
4
5
|
// round, so its own `self` isn't typed with it. Cast once, narrowed to the
|
|
5
6
|
// field table beside it rather than `AnyConfigurationModel`, which is what keeps
|
|
@@ -32,6 +33,12 @@ const confNode = (self) => self;
|
|
|
32
33
|
* means "autoscale this end". Every consumer that computes a domain reads the
|
|
33
34
|
* `*Bound` pair.
|
|
34
35
|
*
|
|
36
|
+
* A display that declares its value scale elsewhere answers
|
|
37
|
+
* `declaredValueScale`, and then the scale type and the pinned bounds come
|
|
38
|
+
* from the declaration rather than from `scaleType`/`minScore`/`maxScore`.
|
|
39
|
+
* Its setters are the display's to override so the edit lands on the same
|
|
40
|
+
* declaration — one owner, whichever it is.
|
|
41
|
+
*
|
|
35
42
|
* Whether a bound is *configured* is a third question, and `hasManualScoreBounds`
|
|
36
43
|
* is the only getter that answers it — the resolved pair cannot, since
|
|
37
44
|
* `defaultScoreDomain` is exactly the hook that turns an unset end into a number.
|
|
@@ -40,11 +47,23 @@ export function ScoreScaleMixin() {
|
|
|
40
47
|
return types
|
|
41
48
|
.model('ScoreScaleMixin', {})
|
|
42
49
|
.views(self => ({
|
|
50
|
+
/**
|
|
51
|
+
* #getter
|
|
52
|
+
* Overridable hook: a value scale the display declares somewhere other
|
|
53
|
+
* than these slots — the mark display's `encoding.y`. Where it answers,
|
|
54
|
+
* it is the owner and the slots below stand in only for the ends it
|
|
55
|
+
* leaves open, so a scale is read from one place whichever place that
|
|
56
|
+
* is. Default none, which is every display whose axis IS these slots.
|
|
57
|
+
*/
|
|
58
|
+
get declaredValueScale() {
|
|
59
|
+
return undefined;
|
|
60
|
+
},
|
|
43
61
|
/**
|
|
44
62
|
* #getter
|
|
45
63
|
*/
|
|
46
64
|
get scaleType() {
|
|
47
|
-
return
|
|
65
|
+
return (this.declaredValueScale?.scaleType ??
|
|
66
|
+
getConf(confNode(self), 'scaleType'));
|
|
48
67
|
},
|
|
49
68
|
/**
|
|
50
69
|
* #getter
|
|
@@ -100,6 +119,10 @@ export function ScoreScaleMixin() {
|
|
|
100
119
|
* The lower bound the config really sets, `undefined` at the sentinel.
|
|
101
120
|
*/
|
|
102
121
|
get manualMinScore() {
|
|
122
|
+
const declared = this.declaredValueScale?.domain?.[0];
|
|
123
|
+
if (declared !== undefined) {
|
|
124
|
+
return declared;
|
|
125
|
+
}
|
|
103
126
|
return this.minScore === Number.MIN_VALUE ? undefined : this.minScore;
|
|
104
127
|
},
|
|
105
128
|
/**
|
|
@@ -107,6 +130,10 @@ export function ScoreScaleMixin() {
|
|
|
107
130
|
* The upper bound the config really sets, `undefined` at the sentinel.
|
|
108
131
|
*/
|
|
109
132
|
get manualMaxScore() {
|
|
133
|
+
const declared = this.declaredValueScale?.domain?.[1];
|
|
134
|
+
if (declared !== undefined) {
|
|
135
|
+
return declared;
|
|
136
|
+
}
|
|
110
137
|
return this.maxScore === Number.MAX_VALUE ? undefined : this.maxScore;
|
|
111
138
|
},
|
|
112
139
|
/**
|
|
@@ -135,6 +162,39 @@ export function ScoreScaleMixin() {
|
|
|
135
162
|
get hasManualScoreBounds() {
|
|
136
163
|
return (this.manualMinScore !== undefined || this.manualMaxScore !== undefined);
|
|
137
164
|
},
|
|
165
|
+
/**
|
|
166
|
+
* #getter
|
|
167
|
+
* Overridable hook (default none): the scales this display draws its y
|
|
168
|
+
* through. A display that answers it gets an axis per band of each,
|
|
169
|
+
* with its cross-hatches, placed by `DisplayChrome` and
|
|
170
|
+
* `renderDisplaySvg`, and the ticks derived below.
|
|
171
|
+
*/
|
|
172
|
+
get valueScales() {
|
|
173
|
+
return [];
|
|
174
|
+
},
|
|
175
|
+
}))
|
|
176
|
+
.views(self => ({
|
|
177
|
+
/**
|
|
178
|
+
* #getter
|
|
179
|
+
* The axes, one per declared scale whose domain resolved: where each
|
|
180
|
+
* tick lands in the band's own pixel space, through `computeYTicks`
|
|
181
|
+
* unless the scale brought its own ladder.
|
|
182
|
+
*/
|
|
183
|
+
get axes() {
|
|
184
|
+
return self.valueScales.flatMap(scale => {
|
|
185
|
+
const { domain } = scale;
|
|
186
|
+
const ticks = scale.ticks ??
|
|
187
|
+
computeYTicks({
|
|
188
|
+
height: scale.height,
|
|
189
|
+
offset: scale.offset,
|
|
190
|
+
domain,
|
|
191
|
+
scaleType: scale.scaleType,
|
|
192
|
+
minimalTicks: scale.minimalTicks ?? false,
|
|
193
|
+
symlogConstant: scale.symlogConstant,
|
|
194
|
+
});
|
|
195
|
+
return domain && ticks ? [{ ...scale, domain, ticks }] : [];
|
|
196
|
+
});
|
|
197
|
+
},
|
|
138
198
|
}))
|
|
139
199
|
.actions(self => ({
|
|
140
200
|
/**
|
package/esm/computeYTicks.d.ts
CHANGED
package/esm/computeYTicks.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { YSCALEBAR_LABEL_OFFSET } from '
|
|
1
|
+
import { YSCALEBAR_LABEL_OFFSET, axisPlotBox } from '@jbrowse/display-ui';
|
|
2
2
|
import { getScale } from './scale.js';
|
|
3
|
-
import { axisPlotBox } from './yScaleTicks.js';
|
|
4
3
|
// Builds Y-axis tick positions for a wiggle-family display: tick values come
|
|
5
4
|
// from d3's scale.ticks(4) at normal heights, or fall back to the domain
|
|
6
5
|
// endpoints for short tracks / when the user opts into minimal ticks.
|
package/esm/constants.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export declare const ONSCREEN_AXIS_LEFT_PX = 50;
|
|
1
|
+
export { YSCALEBAR_LABEL_OFFSET } from '@jbrowse/display-ui/yAxisConstants';
|
package/esm/constants.js
CHANGED
|
@@ -1,10 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// the top/bottom y-axis labels aren't clipped. Lives in its own module because
|
|
3
|
-
// both index.ts (which re-exports computeYTicks) and computeYTicks.ts need it —
|
|
4
|
-
// importing it from index.ts would close a cycle.
|
|
5
|
-
export const YSCALEBAR_LABEL_OFFSET = 5;
|
|
6
|
-
// Left indent of the on-screen y-axis overlay (single-wiggle / manhattan) and of
|
|
7
|
-
// multi-wiggle's per-row scalebars. The axis is right-oriented on screen, so its
|
|
8
|
-
// labels grow into the plot from here; the indent keeps them clear of the track
|
|
9
|
-
// label. Export uses its own anchor (the content left edge).
|
|
10
|
-
export const ONSCREEN_AXIS_LEFT_PX = 50;
|
|
1
|
+
export { YSCALEBAR_LABEL_OFFSET } from '@jbrowse/display-ui/yAxisConstants';
|
package/esm/displayModel.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { WiggleDataResult } from './dataTypes.ts';
|
|
2
2
|
import type { WiggleRenderingBackend } from './renderingBackendTypes.ts';
|
|
3
|
-
import type { YScaleTicks } from './yScaleTicks.ts';
|
|
4
3
|
import type { RegionHost } from '@jbrowse/display-kit/regionHost';
|
|
4
|
+
import type { YScaleTicks } from '@jbrowse/display-ui';
|
|
5
5
|
import type { DisplayPhase } from '@jbrowse/render-core/displayPhase';
|
|
6
6
|
import type { RenderLifecycleModel } from '@jbrowse/render-core/useRenderingBackend';
|
|
7
7
|
export interface WiggleGpuDisplayModel<TRenderingBackend = WiggleRenderingBackend, TData = WiggleDataResult> extends RenderLifecycleModel<TRenderingBackend> {
|
package/esm/index.d.ts
CHANGED
|
@@ -7,15 +7,12 @@ export { SCALE_TYPE_LINEAR, SCALE_TYPE_LOG, SCALE_TYPE_SYMLOG, makeScoreNormaliz
|
|
|
7
7
|
export type { WiggleScaleType } from './normalize.ts';
|
|
8
8
|
export { autoscaleDomainFromStats, computeAutoscaleDomain, computeScoreStats, domainFromStats, getEffectiveScores, } from './autoscale.ts';
|
|
9
9
|
export type { Dataset, FeatureArrays, ScoreStats } from './autoscale.ts';
|
|
10
|
-
export {
|
|
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';
|
|
11
12
|
export { computeYTicks } from './computeYTicks.ts';
|
|
12
13
|
export { resolveRenderState } from './resolveRenderState.ts';
|
|
13
14
|
export { visibleStatsDomain } from './visibleStatsDomain.ts';
|
|
14
15
|
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
16
|
export { parseScoreRules, scoreRuleMarks, widenRangeToRules, } from './scoreRuleMarks.ts';
|
|
20
17
|
export type { ScoreRule, ScoreRuleMark } from './scoreRuleMarks.ts';
|
|
21
18
|
export { makeResolutionSubMenuItem } from './ResolutionStepper.tsx';
|
|
@@ -26,9 +23,6 @@ export { DEFAULT_AUTOSCALE_OPTIONS } from './autoscale.ts';
|
|
|
26
23
|
export { makeAutoscaleTypeSubMenu, makeCrossHatchItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.ts';
|
|
27
24
|
export type { ScoreScaleModel } from './scoreMenuItems.ts';
|
|
28
25
|
export { ScoreScaleMixin } from './ScoreScaleMixin.ts';
|
|
29
|
-
export { default as YScaleBar } from './YScaleBar.tsx';
|
|
30
|
-
export { SvgYScaleGutter, default as YScaleGutter } from './YScaleGutter.tsx';
|
|
31
|
-
export { default as YScaleBarOverlay } from './YScaleBarOverlay.tsx';
|
|
32
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';
|
|
33
27
|
export type { SourceRenderData, WiggleGPURenderState, WiggleRenderingBackend, WiggleRenderingType, } from './renderingBackendTypes.ts';
|
|
34
28
|
export type { SourceInfo, WiggleDataResult, WiggleFeatureArrays, WiggleSourceData, } from './dataTypes.ts';
|
package/esm/index.js
CHANGED
|
@@ -3,13 +3,13 @@ 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, scaleTypeFromString, } from './normalize.js';
|
|
5
5
|
export { autoscaleDomainFromStats, computeAutoscaleDomain, computeScoreStats, domainFromStats, getEffectiveScores, } from './autoscale.js';
|
|
6
|
-
|
|
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';
|
|
7
10
|
export { computeYTicks } from './computeYTicks.js';
|
|
8
11
|
export { resolveRenderState } from './resolveRenderState.js';
|
|
9
12
|
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
13
|
export { parseScoreRules, scoreRuleMarks, widenRangeToRules, } from './scoreRuleMarks.js';
|
|
14
14
|
export { makeResolutionSubMenuItem } from './ResolutionStepper.js';
|
|
15
15
|
export { makeScatterPointSizeMenuItem } from './pointSizeMenu.js';
|
|
@@ -18,9 +18,6 @@ export { default as SetMinMaxDialog } from './SetMinMaxDialog.js';
|
|
|
18
18
|
export { DEFAULT_AUTOSCALE_OPTIONS } from './autoscale.js';
|
|
19
19
|
export { makeAutoscaleTypeSubMenu, makeCrossHatchItem, makeScaleTypeSubMenu, makeScoreSubMenu, makeSetMinMaxScoreItem, } from './scoreMenuItems.js';
|
|
20
20
|
export { ScoreScaleMixin } from './ScoreScaleMixin.js';
|
|
21
|
-
export { default as YScaleBar } from './YScaleBar.js';
|
|
22
|
-
export { SvgYScaleGutter, default as YScaleGutter } from './YScaleGutter.js';
|
|
23
|
-
export { default as YScaleBarOverlay } from './YScaleBarOverlay.js';
|
|
24
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';
|
|
25
22
|
export {} from './displayModel.js';
|
|
26
23
|
export { collectWiggleTransferables } from './transferables.js';
|
package/esm/pointSizeMenu.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { ConfigModelForFields
|
|
1
|
+
import type { ConfigModelForFields } from '@jbrowse/core/configuration';
|
|
2
2
|
import type { MenuItem } from '@jbrowse/core/ui';
|
|
3
3
|
export declare function makeScatterPointSizeMenuItem(self: {
|
|
4
4
|
scatterPointSize: number;
|
|
5
5
|
setScatterPointSize: (n?: number) => void;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
6
|
+
configuration: ConfigModelForFields<{
|
|
7
|
+
scatterPointSize: {
|
|
8
|
+
type: 'number';
|
|
9
|
+
defaultValue: number;
|
|
10
|
+
};
|
|
11
|
+
}>;
|
|
12
|
+
}, opts: {
|
|
12
13
|
label: string;
|
|
13
14
|
}): MenuItem;
|
package/esm/pointSizeMenu.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getSlotDefinition } from '@jbrowse/core/configuration';
|
|
2
|
+
import { makeSizeMenu } from '@jbrowse/core/ui';
|
|
2
3
|
// Wires a display's shared `scatterPointSize`/`setScatterPointSize` (from
|
|
3
|
-
// WiggleScoreConfigMixin) to
|
|
4
|
-
//
|
|
5
|
-
// drift. The `scatterPointSize` slot is promotable, so the row carries the
|
|
6
|
-
// "default for all tracks of this type" pin.
|
|
4
|
+
// WiggleScoreConfigMixin) to makeSizeMenu. Used by both the wiggle scatter and
|
|
5
|
+
// GWAS Manhattan track menus so the slider/reset behavior can't drift.
|
|
7
6
|
export function makeScatterPointSizeMenuItem(self, opts) {
|
|
8
|
-
return
|
|
7
|
+
return makeSizeMenu({
|
|
9
8
|
label: opts.label,
|
|
10
9
|
title: 'Point size',
|
|
11
|
-
display: self,
|
|
12
|
-
slot: 'scatterPointSize',
|
|
13
10
|
getValue: () => self.scatterPointSize,
|
|
11
|
+
isDefault: self.scatterPointSize ===
|
|
12
|
+
getSlotDefinition(self.configuration, 'scatterPointSize').defaultValue,
|
|
14
13
|
onChange: n => {
|
|
15
14
|
self.setScatterPointSize(n);
|
|
16
15
|
},
|
package/esm/scoreRuleMarks.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ScoreRuleMark } from '@jbrowse/display-ui';
|
|
1
2
|
/**
|
|
2
3
|
* #api
|
|
3
4
|
* One horizontal rule across a score plot, at a score the user chose.
|
|
@@ -14,9 +15,7 @@ export interface ScoreRule {
|
|
|
14
15
|
label?: string;
|
|
15
16
|
color?: string;
|
|
16
17
|
}
|
|
17
|
-
export
|
|
18
|
-
y: number;
|
|
19
|
-
}
|
|
18
|
+
export type { ScoreRuleMark } from '@jbrowse/display-ui';
|
|
20
19
|
/**
|
|
21
20
|
* #api
|
|
22
21
|
* Screen y for each rule that falls inside the plotted domain, dropping the
|
package/esm/scoreRuleMarks.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/wiggle-core",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared scale and autoscale utilities for wiggle and coverage displays",
|
|
6
6
|
"keywords": [
|
|
@@ -32,9 +32,10 @@
|
|
|
32
32
|
"@mui/icons-material": "^9.4.0",
|
|
33
33
|
"@mui/material": "^9.4.0",
|
|
34
34
|
"mobx-react": "^10.0.2",
|
|
35
|
-
"@jbrowse/core": "^5.0.0-beta.
|
|
36
|
-
"@jbrowse/
|
|
37
|
-
"@jbrowse/display-
|
|
35
|
+
"@jbrowse/core": "^5.0.0-beta.7",
|
|
36
|
+
"@jbrowse/display-kit": "^5.0.0-beta.7",
|
|
37
|
+
"@jbrowse/display-ui": "^5.0.0-beta.7",
|
|
38
|
+
"@jbrowse/render-core": "^5.0.0-beta.7"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
41
|
"react": ">=19.0.0"
|
package/esm/CrossHatches.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { YScaleTicks } from './yScaleTicks.ts';
|
|
2
|
-
export declare function CrossHatchLines({ ticks, width, offsetY, }: {
|
|
3
|
-
ticks: YScaleTicks;
|
|
4
|
-
width: number;
|
|
5
|
-
offsetY?: number;
|
|
6
|
-
}): import("react").JSX.Element;
|
|
7
|
-
export default function CrossHatches({ ticks, width, height, }: {
|
|
8
|
-
ticks: YScaleTicks;
|
|
9
|
-
width: number;
|
|
10
|
-
height: number;
|
|
11
|
-
}): import("react").JSX.Element;
|
package/esm/CrossHatches.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { clampStrokeInsideAxis } from './yScaleTicks.js';
|
|
3
|
-
// Bare <line> set for the Y-scale tick guide lines, no wrapping <svg>. Shared by
|
|
4
|
-
// the absolutely-positioned on-screen CrossHatches overlay and the flat SVG
|
|
5
|
-
// export (single- and multi-wiggle), so the three can't drift. `offsetY` shifts
|
|
6
|
-
// every line down for per-row rendering in multi-wiggle.
|
|
7
|
-
export function CrossHatchLines({ ticks, width, offsetY = 0, }) {
|
|
8
|
-
return (_jsx(_Fragment, { children: ticks.items.map(({ value, y }) => {
|
|
9
|
-
// Same clamp the axis ticks take, so a guide line and the tick it
|
|
10
|
-
// belongs to can't disagree at the bottom edge — where, in multi-wiggle,
|
|
11
|
-
// "one pixel lower" is the next sample's row. Only that edge moves; the
|
|
12
|
-
// guide lines don't crispen to a half pixel the way the axis does.
|
|
13
|
-
const lineY = offsetY + clampStrokeInsideAxis(y, ticks.yBottom);
|
|
14
|
-
return (_jsx("line", { x1: 0, x2: width, y1: lineY, y2: lineY, stroke: "rgb(200,200,200)",
|
|
15
|
-
// a separate stroke-opacity attribute (not baked into an rgba()
|
|
16
|
-
// string) survives the SVG export, whose renderToStaticMarkup strips
|
|
17
|
-
// rgba() alpha
|
|
18
|
-
strokeOpacity: 0.8, strokeWidth: 1 }, `${value}-${y}`));
|
|
19
|
-
}) }));
|
|
20
|
-
}
|
|
21
|
-
// Horizontal guide lines at each Y-scale tick. Pointer-events disabled so
|
|
22
|
-
// the underlying canvas still receives mouse events.
|
|
23
|
-
export default function CrossHatches({ ticks, width, height, }) {
|
|
24
|
-
return (_jsx("svg", { style: {
|
|
25
|
-
position: 'absolute',
|
|
26
|
-
top: 0,
|
|
27
|
-
left: 0,
|
|
28
|
-
pointerEvents: 'none',
|
|
29
|
-
height,
|
|
30
|
-
width,
|
|
31
|
-
}, children: _jsx(CrossHatchLines, { ticks: ticks, width: width }) }));
|
|
32
|
-
}
|
package/esm/ScoreRules.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { ScoreRuleMark } from './scoreRuleMarks.ts';
|
|
2
|
-
export declare function ScoreRuleLines({ marks, width, offsetY, }: {
|
|
3
|
-
marks: ScoreRuleMark[];
|
|
4
|
-
width: number;
|
|
5
|
-
offsetY?: number;
|
|
6
|
-
}): import("react").JSX.Element;
|
|
7
|
-
export default function ScoreRules({ marks, width, height, }: {
|
|
8
|
-
marks: ScoreRuleMark[];
|
|
9
|
-
width: number;
|
|
10
|
-
height: number;
|
|
11
|
-
}): import("react").JSX.Element;
|
package/esm/ScoreRules.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { usePalette } from '@jbrowse/core/ui/PaletteContext';
|
|
3
|
-
const DEFAULT_RULE_COLOR = 'rgb(120,120,120)';
|
|
4
|
-
// Bare marks, no wrapping <svg>, so the on-screen overlay and the SVG export
|
|
5
|
-
// draw the same elements from the same y. Same split as CrossHatchLines.
|
|
6
|
-
export function ScoreRuleLines({ marks, width, offsetY = 0, }) {
|
|
7
|
-
// A caption sits over the plot, not beside it, so it needs the halo the tick
|
|
8
|
-
// labels next to it already draw (YScaleBar) — without one a rule crossing
|
|
9
|
-
// filled bars captions itself in grey on the fill and cannot be read. From
|
|
10
|
-
// the palette rather than a hardcoded white, which inverts into a glare in
|
|
11
|
-
// dark mode.
|
|
12
|
-
const haloColor = usePalette().background.default;
|
|
13
|
-
return (_jsx(_Fragment, { children: marks.map(({ value, label, color, y }) => {
|
|
14
|
-
const lineY = offsetY + y;
|
|
15
|
-
const stroke = color ?? DEFAULT_RULE_COLOR;
|
|
16
|
-
return (_jsxs("g", { children: [_jsx("line", { x1: 0, x2: width, y1: lineY, y2: lineY, stroke: stroke,
|
|
17
|
-
// separate attribute rather than an rgba() string: the SVG
|
|
18
|
-
// export's renderToStaticMarkup strips rgba() alpha
|
|
19
|
-
strokeOpacity: 0.9, strokeWidth: 1, strokeDasharray: "4 3" }), label ? (_jsx("text", { x: width - 4, y: lineY - 2, textAnchor: "end", fontSize: 10,
|
|
20
|
-
// full alpha, unlike the line: 0.9 is there to let the rule
|
|
21
|
-
// recede into the plot, and a caption that has to be read wants
|
|
22
|
-
// the opposite
|
|
23
|
-
fill: stroke, stroke: haloColor, strokeWidth: 2.5, paintOrder: "stroke", children: label })) : null] }, `${value}-${y}`));
|
|
24
|
-
}) }));
|
|
25
|
-
}
|
|
26
|
-
// Pointer-events disabled so the canvas underneath still gets mouse events,
|
|
27
|
-
// matching CrossHatches.
|
|
28
|
-
export default function ScoreRules({ marks, width, height, }) {
|
|
29
|
-
return (_jsx("svg", { style: {
|
|
30
|
-
position: 'absolute',
|
|
31
|
-
top: 0,
|
|
32
|
-
left: 0,
|
|
33
|
-
pointerEvents: 'none',
|
|
34
|
-
height,
|
|
35
|
-
width,
|
|
36
|
-
}, children: _jsx(ScoreRuleLines, { marks: marks, width: width }) }));
|
|
37
|
-
}
|
package/esm/YScaleBar.d.ts
DELETED
package/esm/YScaleBar.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { usePalette } from '@jbrowse/core/ui/PaletteContext';
|
|
3
|
-
import { clampStrokeInsideAxis } from './yScaleTicks.js';
|
|
4
|
-
// Not an `observer`, and deliberately: there is nothing here to observe. Every
|
|
5
|
-
// caller already reads `model.ticks` inside its own observer and hands the
|
|
6
|
-
// resolved plain object down, and `usePalette` is a React context, not MobX.
|
|
7
|
-
// Wrapping it anyway allocated a Reaction per instance — multi-wiggle renders
|
|
8
|
-
// one per sample row, on screen as well as in export — and, per CLAUDE.md, put
|
|
9
|
-
// the component out of `babel-plugin-react-compiler`'s reach, so it got neither
|
|
10
|
-
// the MobX tracking it doesn't need nor the memoization it does. Its sibling
|
|
11
|
-
// `CrossHatchLines`, consuming the same ticks, is already plain.
|
|
12
|
-
// Half the vertical space a 10px label needs, halo included: digits reach about
|
|
13
|
-
// 3.6px above the centered baseline and the 2.5px-wide background stroke another
|
|
14
|
-
// 1.25px past that.
|
|
15
|
-
const LABEL_HALF_HEIGHT_PX = 5;
|
|
16
|
-
export default function YScaleBar({ ticks, orientation, insetLabels, }) {
|
|
17
|
-
const palette = usePalette();
|
|
18
|
-
if (!ticks) {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
const { items, yTop, yBottom } = ticks;
|
|
22
|
-
const bg = palette.background.default;
|
|
23
|
-
const fg = palette.text.primary;
|
|
24
|
-
const isLeft = orientation !== 'right';
|
|
25
|
-
const k = isLeft ? -1 : 1;
|
|
26
|
-
const tickLength = 6;
|
|
27
|
-
// Crispen to `y + 0.5` so each 1px stroke fills one pixel instead of
|
|
28
|
-
// straddling two, then clamp, which only bites at the bottom edge: there the
|
|
29
|
-
// stroke goes on the last pixel inside the box rather than the first one
|
|
30
|
-
// below it.
|
|
31
|
-
const strokeY = (y) => clampStrokeInsideAxis(y + 0.5, yBottom);
|
|
32
|
-
// The tick keeps the group transform; only the text moves off it, and only
|
|
33
|
-
// under `insetLabels` within half a label of an end. A tick is where the data
|
|
34
|
-
// is, so it never moves — the label is then drawn against the tick rather than
|
|
35
|
-
// across it, which is what any axis does at the edge of its own frame.
|
|
36
|
-
// `undefined` rather than 0 for the labels that don't move, so the markup this
|
|
37
|
-
// emits is unchanged wherever the inset doesn't apply.
|
|
38
|
-
const labelDy = (sy) => {
|
|
39
|
-
if (!insetLabels) {
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
const inset = Math.min(Math.max(sy, yTop + LABEL_HALF_HEIGHT_PX), yBottom - LABEL_HALF_HEIGHT_PX);
|
|
43
|
-
return inset === sy ? undefined : inset - sy;
|
|
44
|
-
};
|
|
45
|
-
return (_jsxs("g", { fontSize: 10, textAnchor: isLeft ? 'end' : 'start', stroke: fg, strokeWidth: 1, children: [_jsx("path", { fill: "none", d: `M${k * tickLength} ${strokeY(yTop)}H0.5V${strokeY(yBottom)}H${k * tickLength}` }), items.map(({ value, y, label }) => (_jsxs("g", { transform: `translate(0,${strokeY(y)})`, children: [_jsx("line", { x2: k * tickLength }), _jsx("text", { stroke: bg, strokeWidth: 2.5, paintOrder: "stroke", fill: fg, y: labelDy(strokeY(y)), dy: "0.32em", x: k * 9, children: label ?? value })] }, `${value}-${y}`)))] }));
|
|
46
|
-
}
|
package/esm/YScaleBarOverlay.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import YScaleBar from './YScaleBar.js';
|
|
3
|
-
import { ONSCREEN_AXIS_LEFT_PX } from './constants.js';
|
|
4
|
-
// Y-axis tick labels positioned absolutely, indented from the track's left edge
|
|
5
|
-
// so a right-oriented axis reads inside the plot. The SVG export instead anchors
|
|
6
|
-
// a left-oriented axis at the content edge, putting the labels in the export
|
|
7
|
-
// margin — see WiggleFamilySvgFrame.
|
|
8
|
-
//
|
|
9
|
-
// `width` is the track's, not a fixed strip: an <svg> clips to its own box, and
|
|
10
|
-
// the hardcoded 70px this used to carry silently truncated any label past ~11
|
|
11
|
-
// characters. Not hypothetical on a log axis — a domain under 1 nices to
|
|
12
|
-
// negative powers of two, so `0.0009765625` is an ordinary tick on a
|
|
13
|
-
// mappability track and the labels grow exactly where the numbers get small.
|
|
14
|
-
// The track's own right edge is the real boundary.
|
|
15
|
-
export default function YScaleBarOverlay({ ticks, height, width, }) {
|
|
16
|
-
return (_jsx("svg", { style: {
|
|
17
|
-
position: 'absolute',
|
|
18
|
-
top: 0,
|
|
19
|
-
left: ONSCREEN_AXIS_LEFT_PX,
|
|
20
|
-
pointerEvents: 'none',
|
|
21
|
-
height,
|
|
22
|
-
width: Math.max(0, width - ONSCREEN_AXIS_LEFT_PX),
|
|
23
|
-
}, children: _jsx(YScaleBar, { ticks: ticks, orientation: "right" }) }));
|
|
24
|
-
}
|
package/esm/YScaleGutter.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { YScaleTicks } from './yScaleTicks.ts';
|
|
2
|
-
/**
|
|
3
|
-
* A left-oriented Y-axis in the shared gutter, at a band's top-left corner on
|
|
4
|
-
* screen. Every stacked band that carries one — the alignments coverage band,
|
|
5
|
-
* MAF's coverage and conservation bands — draws it through this, and its export
|
|
6
|
-
* emits `SvgYScaleGutter` with the same spine placement, so the on-screen and
|
|
7
|
-
* exported axes cannot drift apart.
|
|
8
|
-
*
|
|
9
|
-
* `left` is the gutter's own left edge; the spine is placed inside the gutter
|
|
10
|
-
* from there, so a caller positioning the box does not also offset the spine.
|
|
11
|
-
*/
|
|
12
|
-
export default function YScaleGutter({ top, left, height, ticks, }: {
|
|
13
|
-
top: number;
|
|
14
|
-
left?: number;
|
|
15
|
-
height: number;
|
|
16
|
-
ticks: YScaleTicks;
|
|
17
|
-
}): import("react").JSX.Element;
|
|
18
|
-
/**
|
|
19
|
-
* The gutter's `<g>` on its own, for a caller that already owns an `<svg>` —
|
|
20
|
-
* the SVG export, whose bands are positioned by the enclosing document. `left`
|
|
21
|
-
* is the gutter's left edge in that document.
|
|
22
|
-
*/
|
|
23
|
-
export declare function SvgYScaleGutter({ left, y, ticks, }: {
|
|
24
|
-
left?: number;
|
|
25
|
-
y: number;
|
|
26
|
-
ticks: YScaleTicks;
|
|
27
|
-
}): import("react").JSX.Element;
|
package/esm/YScaleGutter.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import YScaleBar from './YScaleBar.js';
|
|
3
|
-
import { AXIS_GUTTER_WIDTH_PX, leftAxisSpineX } from './yScaleTicks.js';
|
|
4
|
-
/**
|
|
5
|
-
* A left-oriented Y-axis in the shared gutter, at a band's top-left corner on
|
|
6
|
-
* screen. Every stacked band that carries one — the alignments coverage band,
|
|
7
|
-
* MAF's coverage and conservation bands — draws it through this, and its export
|
|
8
|
-
* emits `SvgYScaleGutter` with the same spine placement, so the on-screen and
|
|
9
|
-
* exported axes cannot drift apart.
|
|
10
|
-
*
|
|
11
|
-
* `left` is the gutter's own left edge; the spine is placed inside the gutter
|
|
12
|
-
* from there, so a caller positioning the box does not also offset the spine.
|
|
13
|
-
*/
|
|
14
|
-
export default function YScaleGutter({ top, left = 0, height, ticks, }) {
|
|
15
|
-
return (_jsx("svg", { style: {
|
|
16
|
-
position: 'absolute',
|
|
17
|
-
top,
|
|
18
|
-
left,
|
|
19
|
-
pointerEvents: 'none',
|
|
20
|
-
height,
|
|
21
|
-
width: AXIS_GUTTER_WIDTH_PX,
|
|
22
|
-
}, children: _jsx(SvgYScaleGutter, { y: 0, ticks: ticks }) }));
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* The gutter's `<g>` on its own, for a caller that already owns an `<svg>` —
|
|
26
|
-
* the SVG export, whose bands are positioned by the enclosing document. `left`
|
|
27
|
-
* is the gutter's left edge in that document.
|
|
28
|
-
*/
|
|
29
|
-
export function SvgYScaleGutter({ left = 0, y, ticks, }) {
|
|
30
|
-
return (_jsx("g", { transform: `translate(${leftAxisSpineX(left)}, ${y})`, children: _jsx(YScaleBar, { ticks: ticks, orientation: "left" }) }));
|
|
31
|
-
}
|
package/esm/yScaleTicks.d.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
export interface YScaleTicks {
|
|
2
|
-
items: {
|
|
3
|
-
value: number;
|
|
4
|
-
y: number;
|
|
5
|
-
label?: string;
|
|
6
|
-
}[];
|
|
7
|
-
yTop: number;
|
|
8
|
-
yBottom: number;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* The plot box a wiggle-family display insets inside its own height, for both
|
|
12
|
-
* sides of the contract above: the renderer positions its canvas at `yTop` and
|
|
13
|
-
* draws `plotHeight` tall, and the axis puts domain-max at `yTop` and
|
|
14
|
-
* domain-min at `yBottom`.
|
|
15
|
-
*
|
|
16
|
-
* One function because the two have to agree exactly, and `height - 2 * offset`
|
|
17
|
-
* spelled out at each end is how they stopped: `computeYTicks` derived its own
|
|
18
|
-
* bottom as `height - offset - 1`, and every tick above it inherited a fraction
|
|
19
|
-
* of that pixel.
|
|
20
|
-
*/
|
|
21
|
-
export declare function axisPlotBox(height: number, offset?: number): {
|
|
22
|
-
yTop: number;
|
|
23
|
-
yBottom: number;
|
|
24
|
-
plotHeight: number;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Screen y for an already-normalized ([0,1], 0 at domain-min) score. The
|
|
28
|
-
* composition of {@link axisPlotBox} with a `makeScoreNormalizer` result, which
|
|
29
|
-
* is what a tick at that score must land on.
|
|
30
|
-
*/
|
|
31
|
-
export declare function scoreToAxisY(normalized: number, box: ReturnType<typeof axisPlotBox>): number;
|
|
32
|
-
/**
|
|
33
|
-
* Width of the gutter a left-oriented {@link YScaleBar} is drawn in, and the x
|
|
34
|
-
* inside that gutter its spine goes at.
|
|
35
|
-
*
|
|
36
|
-
* `YScaleBar` grows its ticks and numbers *away* from the spine, so a
|
|
37
|
-
* left-oriented axis has to inset its spine by the label width or the labels
|
|
38
|
-
* land at negative x — which is what once put an exported coverage axis off the
|
|
39
|
-
* image entirely. Both numbers live here, beside the component whose own
|
|
40
|
-
* geometry (`x = ±9`, `fontSize 10`, `textAnchor: end`) is what makes them the
|
|
41
|
-
* right ones: the alignments coverage axis and the MAF band axes had each
|
|
42
|
-
* arrived at this same 50/45 pair independently, so a change to the labels moved
|
|
43
|
-
* neither.
|
|
44
|
-
*
|
|
45
|
-
* An axis drawn over its own plot rather than in reserved space may narrow the
|
|
46
|
-
* gutter — every px of it is a px of data hidden. Such an axis still places its
|
|
47
|
-
* spine at `width - 1`, the same rule stated against its own width.
|
|
48
|
-
*/
|
|
49
|
-
export declare const AXIS_GUTTER_WIDTH_PX = 50;
|
|
50
|
-
export declare function leftAxisSpineX(gutterLeft?: number): number;
|
|
51
|
-
/**
|
|
52
|
-
* Keep a 1px stroke's center inside the axis box. At `yBottom` — the box's own
|
|
53
|
-
* bottom edge — the stroke has to cover the pixel *above* the boundary, since
|
|
54
|
-
* the one below belongs to whatever is drawn next; in multi-wiggle, where rows
|
|
55
|
-
* stack edge to edge, that is literally the next sample's first row of pixels.
|
|
56
|
-
* Callers pass whatever stroke center their own convention gives (the axis
|
|
57
|
-
* crispens to `y + 0.5`, the guide lines don't); only the bottom edge moves.
|
|
58
|
-
*/
|
|
59
|
-
export declare function clampStrokeInsideAxis(strokeY: number, yBottom: number): number;
|
package/esm/yScaleTicks.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { YSCALEBAR_LABEL_OFFSET } from './constants.js';
|
|
2
|
-
/**
|
|
3
|
-
* The plot box a wiggle-family display insets inside its own height, for both
|
|
4
|
-
* sides of the contract above: the renderer positions its canvas at `yTop` and
|
|
5
|
-
* draws `plotHeight` tall, and the axis puts domain-max at `yTop` and
|
|
6
|
-
* domain-min at `yBottom`.
|
|
7
|
-
*
|
|
8
|
-
* One function because the two have to agree exactly, and `height - 2 * offset`
|
|
9
|
-
* spelled out at each end is how they stopped: `computeYTicks` derived its own
|
|
10
|
-
* bottom as `height - offset - 1`, and every tick above it inherited a fraction
|
|
11
|
-
* of that pixel.
|
|
12
|
-
*/
|
|
13
|
-
export function axisPlotBox(height, offset = YSCALEBAR_LABEL_OFFSET) {
|
|
14
|
-
return {
|
|
15
|
-
yTop: offset,
|
|
16
|
-
yBottom: height - offset,
|
|
17
|
-
plotHeight: height - 2 * offset,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Screen y for an already-normalized ([0,1], 0 at domain-min) score. The
|
|
22
|
-
* composition of {@link axisPlotBox} with a `makeScoreNormalizer` result, which
|
|
23
|
-
* is what a tick at that score must land on.
|
|
24
|
-
*/
|
|
25
|
-
export function scoreToAxisY(normalized, box) {
|
|
26
|
-
return box.yTop + (1 - normalized) * box.plotHeight;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Width of the gutter a left-oriented {@link YScaleBar} is drawn in, and the x
|
|
30
|
-
* inside that gutter its spine goes at.
|
|
31
|
-
*
|
|
32
|
-
* `YScaleBar` grows its ticks and numbers *away* from the spine, so a
|
|
33
|
-
* left-oriented axis has to inset its spine by the label width or the labels
|
|
34
|
-
* land at negative x — which is what once put an exported coverage axis off the
|
|
35
|
-
* image entirely. Both numbers live here, beside the component whose own
|
|
36
|
-
* geometry (`x = ±9`, `fontSize 10`, `textAnchor: end`) is what makes them the
|
|
37
|
-
* right ones: the alignments coverage axis and the MAF band axes had each
|
|
38
|
-
* arrived at this same 50/45 pair independently, so a change to the labels moved
|
|
39
|
-
* neither.
|
|
40
|
-
*
|
|
41
|
-
* An axis drawn over its own plot rather than in reserved space may narrow the
|
|
42
|
-
* gutter — every px of it is a px of data hidden. Such an axis still places its
|
|
43
|
-
* spine at `width - 1`, the same rule stated against its own width.
|
|
44
|
-
*/
|
|
45
|
-
export const AXIS_GUTTER_WIDTH_PX = 50;
|
|
46
|
-
export function leftAxisSpineX(gutterLeft = 0) {
|
|
47
|
-
return gutterLeft + AXIS_GUTTER_WIDTH_PX - YSCALEBAR_LABEL_OFFSET;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Keep a 1px stroke's center inside the axis box. At `yBottom` — the box's own
|
|
51
|
-
* bottom edge — the stroke has to cover the pixel *above* the boundary, since
|
|
52
|
-
* the one below belongs to whatever is drawn next; in multi-wiggle, where rows
|
|
53
|
-
* stack edge to edge, that is literally the next sample's first row of pixels.
|
|
54
|
-
* Callers pass whatever stroke center their own convention gives (the axis
|
|
55
|
-
* crispens to `y + 0.5`, the guide lines don't); only the bottom edge moves.
|
|
56
|
-
*/
|
|
57
|
-
export function clampStrokeInsideAxis(strokeY, yBottom) {
|
|
58
|
-
return Math.min(strokeY, yBottom - 0.5);
|
|
59
|
-
}
|