@jbrowse/wiggle-core 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +292 -0
- package/esm/CrossHatches.d.ts +11 -0
- package/esm/CrossHatches.js +32 -0
- package/esm/ResolutionStepper.d.ts +17 -0
- package/esm/ResolutionStepper.js +56 -0
- package/esm/ScoreRules.d.ts +11 -0
- package/esm/ScoreRules.js +37 -0
- package/esm/ScoreScaleMixin.d.ts +105 -0
- package/esm/ScoreScaleMixin.js +136 -0
- package/esm/SetMinMaxDialog.d.ts +11 -0
- package/esm/SetMinMaxDialog.js +18 -0
- package/esm/YScaleBar.d.ts +6 -0
- package/esm/YScaleBar.js +46 -0
- package/esm/YScaleBarOverlay.d.ts +6 -0
- package/esm/YScaleBarOverlay.js +24 -0
- package/esm/autoscale.d.ts +55 -0
- package/esm/autoscale.js +252 -0
- package/esm/computeYTicks.d.ts +15 -0
- package/esm/computeYTicks.js +44 -0
- package/esm/constants.d.ts +2 -0
- package/esm/constants.js +10 -0
- package/esm/dataTypes.d.ts +26 -0
- package/esm/dataTypes.js +1 -0
- package/esm/displayModel.d.ts +24 -0
- package/esm/displayModel.js +1 -0
- package/esm/formatNumber.d.ts +1 -0
- package/esm/formatNumber.js +6 -0
- package/esm/gapBreak.d.ts +59 -0
- package/esm/gapBreak.js +58 -0
- package/esm/index.d.ts +36 -0
- package/esm/index.js +26 -0
- package/esm/normalize.d.ts +40 -0
- package/esm/normalize.js +106 -0
- package/esm/pointMarker.d.ts +3 -0
- package/esm/pointMarker.js +27 -0
- package/esm/pointSizeMenu.d.ts +13 -0
- package/esm/pointSizeMenu.js +21 -0
- package/esm/renderingBackendTypes.d.ts +39 -0
- package/esm/renderingBackendTypes.js +29 -0
- package/esm/resolveRenderState.d.ts +1 -0
- package/esm/resolveRenderState.js +20 -0
- package/esm/scale.d.ts +60 -0
- package/esm/scale.js +161 -0
- package/esm/scoreAxisConfigSchemaFields.d.ts +44 -0
- package/esm/scoreAxisConfigSchemaFields.js +54 -0
- package/esm/scoreMenuItems.d.ts +37 -0
- package/esm/scoreMenuItems.js +104 -0
- package/esm/scoreRuleMarks.d.ts +73 -0
- package/esm/scoreRuleMarks.js +98 -0
- package/esm/symlogTicks.d.ts +17 -0
- package/esm/symlogTicks.js +92 -0
- package/esm/transferables.d.ts +2 -0
- package/esm/transferables.js +32 -0
- package/esm/vendor/d3-scale.d.ts +33 -0
- package/esm/vendor/d3-scale.js +249 -0
- package/esm/visibleStatsDomain.d.ts +59 -0
- package/esm/visibleStatsDomain.js +33 -0
- package/esm/wiggleRenderModes.generated.d.ts +9 -0
- package/esm/wiggleRenderModes.generated.js +11 -0
- package/esm/yScaleTicks.d.ts +59 -0
- package/esm/yScaleTicks.js +59 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [2020] [Evolutionary Software Foundation]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# @jbrowse/wiggle-core
|
|
2
|
+
|
|
3
|
+
Shared scale and autoscale utilities for wiggle and coverage displays
|
|
4
|
+
|
|
5
|
+
<!-- API_DOCS_START -->
|
|
6
|
+
|
|
7
|
+
## API
|
|
8
|
+
|
|
9
|
+
Auto-generated from `#api` JSDoc tags in this package. Do not edit by hand.
|
|
10
|
+
|
|
11
|
+
### computeAutoscaleDomain
|
|
12
|
+
|
|
13
|
+
Computes a score domain from the visible feature arrays for the `local` /
|
|
14
|
+
`localsd` / `localpercentile` autoscale types.
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
// type signature
|
|
18
|
+
(autoscaleType: string, summaryScoreMode: string, numStdDev: number, visibleEntries: {…}[], numQuantile?: number) => [...] | undefined
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/autoscale.ts)
|
|
22
|
+
|
|
23
|
+
### DEFAULT_GAP_BREAK_MULTIPLE
|
|
24
|
+
|
|
25
|
+
Default `multiple` for the wiggle interpolated line — the `maxGapMultiple`
|
|
26
|
+
config slot's default. 0 means the line never breaks: one connected polyline
|
|
27
|
+
across every hole, which is how the interpolated line behaved before gap
|
|
28
|
+
breaking existed.
|
|
29
|
+
|
|
30
|
+
OFF BY DEFAULT, deliberately and after having been on. It shipped at 20 and the
|
|
31
|
+
calibration behind that number still holds — a hole worth breaking on runs
|
|
32
|
+
orders of magnitude past the mean, and bbi's reduced zoom levels emit
|
|
33
|
+
fixed-width bins so the series tiles (measured on volvox_microarray.bw at three
|
|
34
|
+
zooms: 500 bins, every gap exactly 1.0x the mean, no break at any threshold).
|
|
35
|
+
What changed is the call about whether a reader wants the break at all: "we
|
|
36
|
+
added this feature awhile back but i dont think i like it now. might consider
|
|
37
|
+
going back to not skipping". A broken line reads as missing data whether or not
|
|
38
|
+
data is missing there, and the chord across a hole is at least continuous with
|
|
39
|
+
what the neighbouring points say.
|
|
40
|
+
|
|
41
|
+
The mechanism stays, whole, because it is the only way to get the other behavior
|
|
42
|
+
back: set `maxGapMultiple` on the track, 20 being the calibrated value. Nothing
|
|
43
|
+
about `gapBreakLimit` itself changes — a caller passing a positive multiple gets
|
|
44
|
+
exactly what it always got.
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
// type signature
|
|
48
|
+
0
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/gapBreak.ts)
|
|
52
|
+
|
|
53
|
+
### domainFromStats
|
|
54
|
+
|
|
55
|
+
Converts score stats into a `[min, max]` domain, applying std-dev expansion for
|
|
56
|
+
the `localsd` autoscale type.
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
// type signature
|
|
60
|
+
(stats: ScoreStats, autoscaleType: string, numStdDev: number) => [number, number]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/autoscale.ts)
|
|
64
|
+
|
|
65
|
+
### gapBreakLimit
|
|
66
|
+
|
|
67
|
+
How far apart two consecutive points of an interpolated (point-to-point) line
|
|
68
|
+
may be before the span between them counts as a hole rather than a segment to
|
|
69
|
+
draw. Returns `Infinity` when there is nothing to decide, so a caller can always
|
|
70
|
+
compare against it unguarded.
|
|
71
|
+
|
|
72
|
+
The limit is a multiple of the series' own _mean_ spacing rather than an
|
|
73
|
+
absolute distance, which is what makes one number work across zoom levels and
|
|
74
|
+
data types: reduced BigWig bins get wider as you zoom out, so any fixed bp
|
|
75
|
+
threshold would be either useless at one end or destructive at the other. It
|
|
76
|
+
also lets the same rule serve a bp axis (wiggle's linecenter) and a px one — the
|
|
77
|
+
caller picks the space, this only cares that the units are consistent.
|
|
78
|
+
|
|
79
|
+
Mean, not median: it is O(1) from the endpoints, and it errs the safe way. A
|
|
80
|
+
series' holes inflate their own mean, which raises the limit and so breaks
|
|
81
|
+
_less_ — a line that stays connected is the status quo, whereas a spuriously
|
|
82
|
+
broken one destroys data the user can see nowhere else. Sorting for a true
|
|
83
|
+
median would cost O(n log n) per source per region on the encode path, for a
|
|
84
|
+
threshold this coarse.
|
|
85
|
+
|
|
86
|
+
`count < 3` returns Infinity: two points have no "typical" spacing to be unusual
|
|
87
|
+
against, so there is nothing to call a hole.
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
// type signature
|
|
91
|
+
({ first, last, count, multiple, }: { first: number; last: number; count: number; multiple: number; }) => number
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/gapBreak.ts)
|
|
95
|
+
|
|
96
|
+
### getEffectiveScores
|
|
97
|
+
|
|
98
|
+
Per-feature scalar score array for a summary mode: the min/max summary array for
|
|
99
|
+
`'min'`/`'max'`, otherwise the average score.
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
// type signature
|
|
103
|
+
(data: { featureScores: Float32Array<…>; featureMinScores: Float32Array<ArrayBufferLike>; featureMaxScores: Float32Array<...>; }, summaryScoreMode: string) => Float32Array<...>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/autoscale.ts)
|
|
107
|
+
|
|
108
|
+
### getNiceDomain
|
|
109
|
+
|
|
110
|
+
Rounds a domain to "nice" endpoints, clamped to the origin. An end given an
|
|
111
|
+
explicit `bounds` value keeps that value exactly — only an autoscaled end is
|
|
112
|
+
rounded. A log scale's floor still outranks a bound it cannot hold.
|
|
113
|
+
|
|
114
|
+
The result never descends: a bound that would put `min` above `max` widens the
|
|
115
|
+
other end instead, so no consumer has to guess what a backwards domain means.
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
// type signature
|
|
119
|
+
({ scaleType, domain, bounds, }: { scaleType: string; domain: readonly [number, number]; bounds: readonly [number | undefined, number | undefined]; }) => [number, number]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/scale.ts)
|
|
123
|
+
|
|
124
|
+
### getNiceScale
|
|
125
|
+
|
|
126
|
+
Returns a niced `{min, max}` domain for a maximum score value. Uses log base-2
|
|
127
|
+
when `useLogScale` is true (domain is clamped to [1, max]).
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
// type signature
|
|
131
|
+
(maxScore: number, useLogScale?: boolean | undefined) => { min: number; max: number; }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/scale.ts)
|
|
135
|
+
|
|
136
|
+
### getScale
|
|
137
|
+
|
|
138
|
+
Builds a d3 scale (linear/log/symlog) from a `ScaleOpts`, nicing the domain
|
|
139
|
+
unless `nice: false` says it is already the one being drawn with.
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
// type signature
|
|
143
|
+
({ domain, range, scaleType, symlogConstant, nice, }: ScaleOpts) => Scale
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/scale.ts)
|
|
147
|
+
|
|
148
|
+
### makeScoreNormalizer
|
|
149
|
+
|
|
150
|
+
Returns a loop-hoistable function normalizing a score to [0,1].
|
|
151
|
+
|
|
152
|
+
`symlogConstant` is only read for `SCALE_TYPE_SYMLOG`, and is expected to be
|
|
153
|
+
already resolved by resolveSymlogConstant — the shader gets the same resolved
|
|
154
|
+
number as a uniform, so the "auto" rule lives on this side only and the two
|
|
155
|
+
backends compare like for like.
|
|
156
|
+
|
|
157
|
+
A range that is zero **or negative** normalizes everything to 0, which is the
|
|
158
|
+
rule `scoreScale.slang` spells as `range <= 0.0`. Testing `range === 0` here
|
|
159
|
+
instead let a descending domain through to a negative `1 / range`, so every
|
|
160
|
+
score saturated to 1 on this side while the shader flattened them all to 0 — one
|
|
161
|
+
view, opposite plots. `normalizeScoreParity.test.ts` sweeps the two.
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
// type signature
|
|
165
|
+
(min: number, max: number, scaleType: WiggleScaleType, symlogConstant?: number) => (score: number) => number
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/normalize.ts)
|
|
169
|
+
|
|
170
|
+
### parseScoreRules
|
|
171
|
+
|
|
172
|
+
Normalizes whatever a `scoreRules` config slot holds into `ScoreRule`s, dropping
|
|
173
|
+
entries that are not usable. Config is user-authored JSON, so a bare number, a
|
|
174
|
+
missing value or a non-numeric one all have to survive being read.
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
// type signature
|
|
178
|
+
(value: unknown) => ScoreRule[]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/scoreRuleMarks.ts)
|
|
182
|
+
|
|
183
|
+
### resolveSymlogConstant
|
|
184
|
+
|
|
185
|
+
The symlog constant actually used for a domain. `0` (the config default) means
|
|
186
|
+
"pick one from the domain": a thousandth of its largest magnitude, so the
|
|
187
|
+
log-ish part of the curve covers the top three decades of whatever the track
|
|
188
|
+
holds and the linear knee sits below the data rather than through it.
|
|
189
|
+
|
|
190
|
+
The alternative — d3's default of 1 — is `log(x + 1)`, which is fine for read
|
|
191
|
+
depth and useless for anything living below 1, because the entire domain then
|
|
192
|
+
falls in the linear part of the curve. A p-value track configured that way is
|
|
193
|
+
just a linear track wearing a log label, which is the reason this is resolved
|
|
194
|
+
rather than hard-coded.
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
// type signature
|
|
198
|
+
(min: number, max: number, configured: number) => number
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/normalize.ts)
|
|
202
|
+
|
|
203
|
+
### scaleTypeFromString
|
|
204
|
+
|
|
205
|
+
Maps the `'log'`/`'symlog'`/`'linear'` string to the numeric `WiggleScaleType`.
|
|
206
|
+
|
|
207
|
+
```js
|
|
208
|
+
// type signature
|
|
209
|
+
(scaleType: string) => WiggleScaleType
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/normalize.ts)
|
|
213
|
+
|
|
214
|
+
### ScoreRule
|
|
215
|
+
|
|
216
|
+
One horizontal rule across a score plot, at a score the user chose.
|
|
217
|
+
|
|
218
|
+
`label` is free text and carries no meaning this package assigns. That is
|
|
219
|
+
deliberate: the obvious use is reading a coverage or CNV track against copy
|
|
220
|
+
number, and there is no ploidy JBrowse could assume on the user's behalf. A
|
|
221
|
+
whole-genome triplication is not diploid, plenty of genomes are not diploid to
|
|
222
|
+
begin with, and a cancer sample can be neither — so "2 copies" is a claim only
|
|
223
|
+
the person looking at the track can make.
|
|
224
|
+
|
|
225
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/scoreRuleMarks.ts)
|
|
226
|
+
|
|
227
|
+
### scoreRuleMarks
|
|
228
|
+
|
|
229
|
+
Screen y for each rule that falls inside the plotted domain, dropping the rest.
|
|
230
|
+
|
|
231
|
+
Out-of-domain is a real case rather than a guard: the domain is whatever
|
|
232
|
+
autoscale resolved for the visible data, so panning to a quiet stretch can put a
|
|
233
|
+
rule above everything on screen, and a rule pinned to the top edge there reads
|
|
234
|
+
as "the whole view is over the line".
|
|
235
|
+
|
|
236
|
+
`normalize` is the display's OWN score normalizer — the same one the renderer
|
|
237
|
+
draws with. It is a parameter rather than a linear interpolation of the domain
|
|
238
|
+
because the axis need not be linear: on a log or symlog track, placing a rule at
|
|
239
|
+
`(value - min) / (max - min)` puts the line somewhere the data it is meant to be
|
|
240
|
+
read against is not.
|
|
241
|
+
|
|
242
|
+
`box` is likewise the caller's own — hand it the same `{yTop, yBottom}` the
|
|
243
|
+
display's ticks were built with (a `YScaleTicks` satisfies it). Recomputing a
|
|
244
|
+
box here would silently disagree with any band that lays its axis out
|
|
245
|
+
differently, and the alignments coverage band does.
|
|
246
|
+
|
|
247
|
+
```js
|
|
248
|
+
// type signature
|
|
249
|
+
({…}: { rules: readonly ScoreRule[]; domain: [number, number] | undefined; box: { yTop: number; yBottom: number; }; normalize: (score: number) => number; }) => ScoreRuleMark[]
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/scoreRuleMarks.ts)
|
|
253
|
+
|
|
254
|
+
### visibleStatsDomain
|
|
255
|
+
|
|
256
|
+
The visible score domain four displays derive identically: walk the settled
|
|
257
|
+
blocks, accumulate the stats of what each one shows, and nice-round the
|
|
258
|
+
autoscaled range inside the configured bounds. `undefined` while there is
|
|
259
|
+
nothing to scale against — no data, a hidden band, or a view that has not
|
|
260
|
+
initialized — which every caller distinguishes from a domain.
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
// type signature
|
|
264
|
+
<Payload, Item, Stats>({ active, view, payloadFor, itemsFor, accumulate, range, bounds, scaleType, }: VisibleStatsDomainSpec<Payload, Item, Stats>) => [number, number] | undefined
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/visibleStatsDomain.ts)
|
|
268
|
+
|
|
269
|
+
### widenRangeToRules
|
|
270
|
+
|
|
271
|
+
Widens an autoscaled range so every configured rule stays on the axis.
|
|
272
|
+
|
|
273
|
+
Without this a rule silently disappears in exactly the window that makes it
|
|
274
|
+
worth having. Autoscale follows the visible data, so over a homozygous deletion
|
|
275
|
+
a coverage domain collapses to about `[0, 1]` and a rule at the diploid depth
|
|
276
|
+
falls outside it — and "2 copies would be up there" is the most informative
|
|
277
|
+
thing that view can say. The reader has no menu to check either: `scoreRules` is
|
|
278
|
+
set by whoever wrote the config, so a rule that vanishes leaves nothing behind
|
|
279
|
+
to notice.
|
|
280
|
+
|
|
281
|
+
Applied to the raw range, before `getNiceDomain` takes the `minScore` /
|
|
282
|
+
`maxScore` bounds. Those still win: a rule outside an explicitly bounded axis is
|
|
283
|
+
one the config asked not to be shown, and it drops as before.
|
|
284
|
+
|
|
285
|
+
```js
|
|
286
|
+
// type signature
|
|
287
|
+
(range: [number, number], ruleValues: readonly number[]) => [number, number]
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/wiggle-core/src/scoreRuleMarks.ts)
|
|
291
|
+
|
|
292
|
+
<!-- API_DOCS_END -->
|
|
@@ -0,0 +1,11 @@
|
|
|
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;
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MenuItem } from '@jbrowse/core/ui';
|
|
2
|
+
import type React from 'react';
|
|
3
|
+
interface ResolutionStepperState {
|
|
4
|
+
label: string;
|
|
5
|
+
finerDisabled: boolean;
|
|
6
|
+
coarserDisabled: boolean;
|
|
7
|
+
resetDisabled: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function makeResolutionSubMenuItem(opts: {
|
|
10
|
+
getState: () => ResolutionStepperState;
|
|
11
|
+
onFiner: () => void;
|
|
12
|
+
onCoarser: () => void;
|
|
13
|
+
onReset: () => void;
|
|
14
|
+
icon?: React.ElementType;
|
|
15
|
+
resetTitle?: string;
|
|
16
|
+
}): MenuItem;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { INLINE_MENU_ROW_WIDTH, ResetToDefaultButton } from '@jbrowse/core/ui';
|
|
3
|
+
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
4
|
+
import { Button, Typography } from '@mui/material';
|
|
5
|
+
import { observer } from 'mobx-react';
|
|
6
|
+
const useStyles = makeStyles()(theme => ({
|
|
7
|
+
row: {
|
|
8
|
+
display: 'flex',
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
gap: theme.spacing(0.5),
|
|
11
|
+
width: INLINE_MENU_ROW_WIDTH,
|
|
12
|
+
},
|
|
13
|
+
// subtle text buttons: no uppercase, minimal padding, inherit text color so
|
|
14
|
+
// "Coarser"/"Finer" read as quiet affordances rather than prominent CTAs
|
|
15
|
+
step: {
|
|
16
|
+
textTransform: 'none',
|
|
17
|
+
minWidth: 0,
|
|
18
|
+
padding: '0 4px',
|
|
19
|
+
},
|
|
20
|
+
value: {
|
|
21
|
+
flex: 1,
|
|
22
|
+
textAlign: 'center',
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
// Subtle inline stepper: [−] label [+] [reset]. The −/+ icon buttons let the
|
|
26
|
+
// user step finer/coarser repeatedly without reopening the menu. Shared by the
|
|
27
|
+
// wiggle binning multiplier and the Hi-C matrix binsize, which differ only in
|
|
28
|
+
// how they format the label and bound the steps.
|
|
29
|
+
const ResolutionStepper = observer(function ResolutionStepper({ getState, onFiner, onCoarser, onReset, resetTitle, }) {
|
|
30
|
+
const { classes } = useStyles();
|
|
31
|
+
const { label, finerDisabled, coarserDisabled, resetDisabled } = getState();
|
|
32
|
+
return (_jsxs("div", { className: classes.row, children: [_jsx(Button, { className: classes.step, size: "small", color: "inherit", disabled: coarserDisabled, onClick: () => {
|
|
33
|
+
onCoarser();
|
|
34
|
+
}, children: "Coarser" }), _jsx(Typography, { variant: "caption", color: "textSecondary", className: classes.value, children: label }), _jsx(Button, { className: classes.step, size: "small", color: "inherit", disabled: finerDisabled, onClick: () => {
|
|
35
|
+
onFiner();
|
|
36
|
+
}, children: "Finer" }), _jsx(ResetToDefaultButton, { title: resetTitle, disabled: resetDisabled, onClick: () => {
|
|
37
|
+
onReset();
|
|
38
|
+
} })] }));
|
|
39
|
+
});
|
|
40
|
+
// A "Resolution" submenu whose single row is the inline stepper, so it sits
|
|
41
|
+
// alongside the other track-menu submenus but keeps the menu open while
|
|
42
|
+
// stepping. Callers own the label formatting, step bounds, and step actions.
|
|
43
|
+
export function makeResolutionSubMenuItem(opts) {
|
|
44
|
+
const { getState, onFiner, onCoarser, onReset, icon, resetTitle } = opts;
|
|
45
|
+
return {
|
|
46
|
+
label: 'Resolution',
|
|
47
|
+
icon,
|
|
48
|
+
subMenu: [
|
|
49
|
+
{
|
|
50
|
+
label: 'Resolution stepper',
|
|
51
|
+
type: 'custom',
|
|
52
|
+
render: () => (_jsx(ResolutionStepper, { getState: getState, onFiner: onFiner, onCoarser: onCoarser, onReset: onReset, resetTitle: resetTitle })),
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
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;
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
}
|