@jbrowse/core 5.0.0-beta.1 → 5.0.0-beta.3
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/README.md +112 -43
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.d.ts +4 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.js +17 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +4 -3
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +2 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.d.ts +2 -2
- package/esm/BaseFeatureWidget/index.d.ts +1 -1
- package/esm/BaseFeatureWidget/stateModelFactory.d.ts +8 -1
- package/esm/BaseFeatureWidget/stateModelFactory.js +6 -0
- package/esm/BaseFeatureWidget/types.d.ts +10 -2
- package/esm/PluginLoader.d.ts +1 -0
- package/esm/PluginLoader.js +52 -8
- package/esm/PluginManager.d.ts +99 -17
- package/esm/PluginManager.js +194 -26
- package/esm/ReExports/BaseFeatureDetails.js +1 -1
- package/esm/ReExports/MuiDataGridReExports.d.ts +1 -0
- package/esm/ReExports/MuiDataGridReExports.js +2 -2
- package/esm/ReExports/barrelOnlyNames.d.ts +5 -0
- package/esm/ReExports/barrelOnlyNames.js +63 -0
- package/esm/ReExports/modules.js +31 -109
- package/esm/ReExports/publicTracks.d.ts +1 -0
- package/esm/ReExports/publicTracks.js +14 -0
- package/esm/ReExports/publicUi.d.ts +4 -0
- package/esm/ReExports/publicUi.js +33 -0
- package/esm/ReExports/publicUtil.d.ts +1 -1
- package/esm/ReExports/publicUtil.js +8 -4
- package/esm/ReExports/sharedModules.d.ts +96 -0
- package/esm/ReExports/sharedModules.js +66 -0
- package/esm/ReExports/uiStub.d.ts +2 -0
- package/esm/ReExports/uiStub.js +11 -0
- package/esm/ReExports/workerModules.d.ts +2 -0
- package/esm/ReExports/workerModules.js +15 -0
- package/esm/ReExports/workerNamespaceNames.d.ts +11 -0
- package/esm/ReExports/workerNamespaceNames.js +281 -0
- package/esm/configuration/configurationSchema.d.ts +5 -38
- package/esm/configuration/configurationSchema.js +64 -40
- package/esm/configuration/index.d.ts +2 -2
- package/esm/configuration/index.js +1 -1
- package/esm/configuration/promotableDefaults.d.ts +54 -19
- package/esm/configuration/promotableDefaults.js +117 -48
- package/esm/configuration/promotablePin.d.ts +50 -40
- package/esm/configuration/promotableResolve.d.ts +1 -1
- package/esm/configuration/promotableResolve.js +1 -1
- package/esm/configuration/tabixIndexFields.d.ts +2 -2
- package/esm/configuration/tabixIndexFields.js +2 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +12 -0
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +35 -4
- package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +41 -0
- package/esm/data_adapters/BaseAdapter/featureDensity.js +32 -0
- package/esm/data_adapters/BaseAdapter/index.d.ts +2 -1
- package/esm/data_adapters/BaseAdapter/index.js +1 -0
- package/esm/data_adapters/BaseAdapter/stats.d.ts +33 -1
- package/esm/data_adapters/BaseAdapter/stats.js +52 -13
- package/esm/data_adapters/BaseAdapter/types.d.ts +3 -8
- package/esm/pluggableElementTypes/AdapterType.d.ts +2 -1
- package/esm/pluggableElementTypes/AdapterType.js +1 -1
- package/esm/pluggableElementTypes/DisplayType.d.ts +4 -12
- package/esm/pluggableElementTypes/DisplayType.js +3 -10
- package/esm/pluggableElementTypes/LazyStateModelElement.d.ts +27 -0
- package/esm/pluggableElementTypes/LazyStateModelElement.js +71 -0
- package/esm/pluggableElementTypes/ViewType.d.ts +20 -4
- package/esm/pluggableElementTypes/ViewType.js +32 -4
- package/esm/pluggableElementTypes/extendElementType.d.ts +1 -2
- package/esm/pluggableElementTypes/extendElementType.js +9 -5
- package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +44 -3
- package/esm/pluggableElementTypes/models/BaseDisplayModel.js +75 -2
- package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +21 -0
- package/esm/pluggableElementTypes/models/BaseTrackModel.js +34 -2
- package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +49 -0
- package/esm/pluggableElementTypes/models/BaseViewModel.js +28 -0
- package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +14 -10
- package/esm/pluggableElementTypes/models/assertDisplayContract.js +25 -32
- package/esm/pluggableElementTypes/models/baseTrackConfig.js +7 -1
- package/esm/rpc/RpcRegistry.d.ts +10 -0
- package/esm/rpc/byteBudget.d.ts +9 -0
- package/esm/rpc/coreRpcMethods.d.ts +1 -0
- package/esm/rpc/coreRpcMethods.js +1 -0
- package/esm/rpc/methods/CoreGetFeatureDensity.d.ts +11 -0
- package/esm/rpc/methods/CoreGetFeatureDensity.js +22 -0
- package/esm/svg/svgReady.d.ts +1 -0
- package/esm/ui/BaseExportSvgDialog.d.ts +1 -1
- package/esm/ui/CascadingMenu.js +30 -8
- package/esm/ui/ErrorMessageStackTraceDialog.js +5 -6
- package/esm/ui/ExportSvgDialog.d.ts +1 -1
- package/esm/ui/LoadingOverlay.d.ts +14 -0
- package/esm/ui/LoadingOverlay.js +1 -1
- package/esm/ui/MenuTypes.d.ts +14 -5
- package/esm/ui/MenuTypes.js +3 -0
- package/esm/ui/PaletteContext.d.ts +11 -4
- package/esm/ui/PaletteContext.js +34 -5
- package/esm/ui/PinAdornment.js +31 -43
- package/esm/ui/ScrollChrome.d.ts +16 -0
- package/esm/ui/ScrollChrome.js +12 -0
- package/esm/ui/ScrollZoomToggle.d.ts +4 -3
- package/esm/ui/ScrollZoomToggle.js +4 -3
- package/esm/ui/SizeSliderRow.js +1 -1
- package/esm/ui/index.d.ts +3 -3
- package/esm/ui/index.js +4 -4
- package/esm/ui/launchViewMenu.js +7 -1
- package/esm/ui/legendMenuItem.d.ts +10 -16
- package/esm/ui/legendMenuItem.js +9 -20
- package/esm/ui/makeSizeMenu.js +1 -1
- package/esm/ui/menuItemAdornment.d.ts +2 -3
- package/esm/ui/menuItemAdornment.js +2 -3
- package/esm/ui/menuItems.d.ts +2 -3
- package/esm/ui/menuItems.js +1 -2
- package/esm/ui/palette.d.ts +11 -11
- package/esm/ui/palette.js +11 -11
- package/esm/ui/promotablePinCoverage.d.ts +16 -2
- package/esm/ui/promotablePinCoverage.js +40 -3
- package/esm/ui/theme.js +5 -0
- package/esm/ui/toggleMenuItems.d.ts +14 -9
- package/esm/ui/toggleMenuItems.js +32 -15
- package/esm/util/Base1DUtils.d.ts +4 -2
- package/esm/util/Base1DUtils.js +12 -4
- package/esm/util/SvgCanvas.js +4 -3
- package/esm/util/adapterConfigKey.d.ts +12 -0
- package/esm/util/adapterConfigKey.js +14 -0
- package/esm/util/adapterMetadata.js +2 -1
- package/esm/util/addAndShowTrack.d.ts +1 -1
- package/esm/util/addAndShowTrack.js +5 -1
- package/esm/util/addTrackFromWidget.js +2 -2
- package/esm/util/analytics.js +4 -5
- package/esm/util/cacheBudgets.d.ts +22 -19
- package/esm/util/cacheBudgets.js +22 -19
- package/esm/util/clampToContig.d.ts +17 -0
- package/esm/util/clampToContig.js +19 -0
- package/esm/util/colorBits.d.ts +2 -1
- package/esm/util/colorBits.js +2 -5
- package/esm/util/createStopTokenRotation.d.ts +9 -7
- package/esm/util/createStopTokenRotation.js +7 -27
- package/esm/util/featureTypes.d.ts +24 -0
- package/esm/util/featureTypes.js +35 -0
- package/esm/util/fetchContext.d.ts +2 -2
- package/esm/util/fetchContext.js +2 -2
- package/esm/util/fetchPhases.d.ts +10 -10
- package/esm/util/hooks.d.ts +8 -0
- package/esm/util/hooks.js +27 -0
- package/esm/util/index.d.ts +6 -5
- package/esm/util/index.js +5 -4
- package/esm/util/installFetch.d.ts +71 -34
- package/esm/util/installFetch.js +57 -29
- package/esm/util/installInitAutorun.d.ts +14 -13
- package/esm/util/installInitAutorun.js +17 -17
- package/esm/util/installPrerequisiteFetch.d.ts +86 -0
- package/esm/util/installPrerequisiteFetch.js +73 -0
- package/esm/util/lazyAfterAttach.d.ts +13 -0
- package/esm/util/lazyAfterAttach.js +31 -0
- package/esm/util/legendCandidates.d.ts +50 -0
- package/esm/util/legendCandidates.js +87 -0
- package/esm/util/mstUtils.d.ts +12 -1
- package/esm/util/mstUtils.js +20 -2
- package/esm/util/openFeatureWidget.d.ts +5 -0
- package/esm/util/openFeatureWidget.js +1 -0
- package/esm/util/openViews.d.ts +16 -0
- package/esm/util/openViews.js +22 -0
- package/esm/util/parentWalk.d.ts +1 -1
- package/esm/util/parentWalk.js +1 -1
- package/esm/util/pluginStore.d.ts +1 -0
- package/esm/util/pluginStore.js +8 -1
- package/esm/util/range.d.ts +13 -9
- package/esm/util/range.js +17 -8
- package/esm/util/renderToStaticMarkup.js +10 -0
- package/esm/util/rxjs.d.ts +16 -0
- package/esm/util/rxjs.js +49 -0
- package/esm/util/scheduleDetachedDestroy.d.ts +18 -0
- package/esm/util/scheduleDetachedDestroy.js +24 -0
- package/esm/util/scrollLatch.d.ts +1 -0
- package/esm/util/scrollLatch.js +8 -0
- package/esm/util/stopToken.d.ts +6 -5
- package/esm/util/tabix.d.ts +10 -4
- package/esm/util/tabix.js +11 -5
- package/esm/util/trackConfigDelta.d.ts +6 -6
- package/esm/util/trackConfigDelta.js +3 -3
- package/esm/util/tracks.d.ts +48 -0
- package/esm/util/tracks.js +192 -66
- package/esm/util/types/index.d.ts +58 -10
- package/esm/util/types/index.js +3 -0
- package/esm/util/unknownSnapshotKeys.d.ts +36 -0
- package/esm/util/unknownSnapshotKeys.js +69 -0
- package/esm/util/usePanelVirtualScroll.d.ts +6 -2
- package/esm/util/usePanelVirtualScroll.js +6 -2
- package/esm/util/useRowVirtualScroll.d.ts +1 -1
- package/esm/util/useRowVirtualScroll.js +1 -1
- package/esm/util/useVirtualScrollWheel.js +11 -1
- package/esm/util/viewStatus.d.ts +23 -0
- package/esm/util/viewStatus.js +17 -0
- package/esm/util/wheelZoom.d.ts +3 -1
- package/esm/util/wheelZoom.js +39 -14
- package/esm/util/whenViewSettled.d.ts +17 -4
- package/esm/util/whenViewSettled.js +19 -6
- package/esm/util/withLaunchInput.d.ts +168 -0
- package/esm/util/withLaunchInput.js +273 -0
- package/package.json +19 -11
- package/esm/ui/promotableMenuItems.d.ts +0 -19
- package/esm/ui/promotableMenuItems.js +0 -89
- package/esm/util/applyInitSettings.d.ts +0 -79
- package/esm/util/applyInitSettings.js +0 -91
|
@@ -24,10 +24,10 @@ import { isConfigurationModel } from './schemaTypes.js';
|
|
|
24
24
|
* base instead reads as at-default for a track merely *following* a non-base
|
|
25
25
|
* promoted default, so the reset control lights up on a no-op.
|
|
26
26
|
*
|
|
27
|
-
* `SLOT` is constrained the way `getConf`'s is
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* `SLOT` is constrained the way `getConf`'s is, and a widened `self` switches
|
|
28
|
+
* the check off (`HostChecksSlotNames`). A slot name the schema does not
|
|
29
|
+
* declare throws at the first read (`getSlotDefinition`), and a declared but
|
|
30
|
+
* non-promotable one throws in `resolveSlotIn`.
|
|
31
31
|
*/
|
|
32
32
|
export function isSlotCustomized(self, slot) {
|
|
33
33
|
return resolveSlot(self, slot).customized;
|
|
@@ -178,62 +178,79 @@ export function applySlotToOpenTracks(displays, slot, value) {
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
|
-
* The pin's click
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* user is the click they mean far more often, so it is the one that needs no
|
|
187
|
-
* second click; a default outlives the tracks it was set for and governs every
|
|
188
|
-
* track of the type opened later, so it is the escalation (ADR-048).
|
|
189
|
-
* - **It is** — clear it, touching no track. The open tracks hold their values
|
|
190
|
-
* because the user applied them, so reverting them here would make a toggle
|
|
191
|
-
* into a bulk discard.
|
|
181
|
+
* The pin's click: write `value` into every open track of the type, and offer
|
|
182
|
+
* the promotion as a snackbar action. Applying to the tracks in front of the
|
|
183
|
+
* user is the click they mean far more often, so it is the one that needs no
|
|
184
|
+
* second click; a default outlives the tracks it was set for and governs every
|
|
185
|
+
* track of the type opened later, so it is the escalation (ADR-048).
|
|
192
186
|
*
|
|
193
187
|
* The apply is one operation over *every* open track, not a labeled pair over
|
|
194
188
|
* the tracks that differ and the tracks that follow. Overwriting a customized
|
|
195
189
|
* track is the same write as filling in a follower, and the distinction the two
|
|
196
190
|
* actions drew is not one the user has any reason to see.
|
|
197
191
|
*
|
|
198
|
-
* The snackbar outlives the click that raised it, so the promotion
|
|
199
|
-
*
|
|
200
|
-
*
|
|
192
|
+
* The snackbar outlives the click that raised it, so the promotion closes over
|
|
193
|
+
* the display TYPE — a string — rather than reaching back through `self`. A
|
|
194
|
+
* promoted default is keyed by display type and governs tracks opened later, so
|
|
195
|
+
* it has nothing to do with the clicked display still being open; guarding on
|
|
196
|
+
* `self` instead meant a user who applied a value, closed the track, then took
|
|
197
|
+
* the offer got a silent no-op. What is still guarded is the session, which owns
|
|
198
|
+
* the map the write lands in. ADR-048 has the decisions this does not change:
|
|
199
|
+
* no track set and no apply/promote decision may be closed over.
|
|
200
|
+
*
|
|
201
|
+
* **Promoting the slot's base value clears the default instead of storing it.**
|
|
202
|
+
* The cascade resolves the two identically, but a stored base was a third
|
|
203
|
+
* state the rest of the subsystem could see: the Preferences inventory listed a
|
|
204
|
+
* row reading "from X to X", and the base option's radio pin drew filled. Now
|
|
205
|
+
* "Set as the default" on the base row is the per-value way to undo a promoted
|
|
206
|
+
* default, and a filled pin only ever means a non-base value is promoted. The
|
|
207
|
+
* base is read here rather than at click time because it is a schema literal
|
|
208
|
+
* and cannot change.
|
|
201
209
|
*/
|
|
202
|
-
function
|
|
210
|
+
function applyAndOfferDefault(self, slot, value) {
|
|
203
211
|
const session = getSession(self);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
212
|
+
const displayType = self.type;
|
|
213
|
+
const { base } = resolveSlot(self, slot);
|
|
214
|
+
const promoted = deepEqual(value, base) ? undefined : value;
|
|
215
|
+
const open = openTracksOfType(self);
|
|
216
|
+
applySlotToOpenTracks(open, slot, value);
|
|
217
|
+
session.notify(`Applied to ${open.length} open ${pluralize(open.length, 'track')}`, 'info', {
|
|
218
|
+
name: 'Set as the default',
|
|
219
|
+
onClick: () => {
|
|
220
|
+
if (isAlive(session)) {
|
|
221
|
+
session.setDisplayTypeDefault(displayType, slot, promoted);
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* A value pin's click when its value is already the promoted default: clear
|
|
228
|
+
* it, touching no track. The open tracks hold their values because the user
|
|
229
|
+
* applied them, so reverting them here would make a toggle into a bulk discard.
|
|
230
|
+
*/
|
|
231
|
+
function clearDefault(self, slot) {
|
|
232
|
+
const session = getSession(self);
|
|
233
|
+
session.setDisplayTypeDefault(self.type, slot, undefined);
|
|
234
|
+
session.notify('Cleared the default', 'info');
|
|
220
235
|
}
|
|
221
236
|
/**
|
|
222
237
|
* #api core/configuration
|
|
223
|
-
* The pin
|
|
224
|
-
* display type", and — via the snackbar it raises — "keep it as the
|
|
225
|
-
* the ones opened later".
|
|
238
|
+
* The pin on a radio or slider row: "apply this value to every open track of
|
|
239
|
+
* this display type", and — via the snackbar it raises — "keep it as the
|
|
240
|
+
* default for the ones opened later".
|
|
226
241
|
*
|
|
227
242
|
* `value` chooses between the subsystem's two meanings, which are otherwise
|
|
228
243
|
* identical:
|
|
229
244
|
*
|
|
230
|
-
* - **Give it** for a per-value pin — "make *
|
|
231
|
-
* what the track currently shows. Use on an always-visible pin
|
|
232
|
-
* promote a meaningless value, and so two rows sharing one
|
|
233
|
-
*
|
|
245
|
+
* - **Give it** for a per-value pin — "make *compact* the default" —
|
|
246
|
+
* independent of what the track currently shows. Use on an always-visible pin
|
|
247
|
+
* so it can never promote a meaningless value, and so two rows sharing one
|
|
248
|
+
* slot (sashimi `'down'` vs `'auto'`) stay independent.
|
|
234
249
|
* - **Omit it** for "whatever I'm showing", resolved through the cascade. Use for
|
|
235
|
-
* a
|
|
236
|
-
*
|
|
250
|
+
* a continuous setting where no fixed on-value makes sense (wiggle point size,
|
|
251
|
+
* arc line width).
|
|
252
|
+
*
|
|
253
|
+
* A checkbox row takes neither: {@link makeTogglePin}.
|
|
237
254
|
*
|
|
238
255
|
* One function with an optional argument, rather than the two exported builders
|
|
239
256
|
* it replaces — a per-value one and a `…CurrentValue…` one, the second of which
|
|
@@ -271,11 +288,63 @@ export function makePin(self, slot, ...value) {
|
|
|
271
288
|
// same `deepEqual`, no second walk.
|
|
272
289
|
const active = deepEqual(res.promoted, onValue);
|
|
273
290
|
return {
|
|
291
|
+
kind: 'value',
|
|
292
|
+
slot,
|
|
293
|
+
onValue,
|
|
294
|
+
active,
|
|
295
|
+
toggle: () => {
|
|
296
|
+
if (active) {
|
|
297
|
+
clearDefault(self, slot);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
applyAndOfferDefault(self, slot, onValue);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* #api core/configuration
|
|
307
|
+
* The pin on a checkbox row: the row's own checkbox, acting on every open track
|
|
308
|
+
* of the display type. `active` mirrors the row, so the pin draws filled
|
|
309
|
+
* exactly when the box is ticked; a click flips the row's state on every open
|
|
310
|
+
* track and offers the new state as the display type's default. It never
|
|
311
|
+
* clears a default the way {@link makePin}'s filled pin does — flipping back
|
|
312
|
+
* and taking the offer promotes the other value, and promoting the base value
|
|
313
|
+
* clears the default (`applyAndOfferDefault`).
|
|
314
|
+
*
|
|
315
|
+
* Replaces a symmetric `makePin(self, slot)` on these rows, which carried the
|
|
316
|
+
* row's current state: beside an unchecked box that applied *off* everywhere
|
|
317
|
+
* and visibly did nothing. It also replaces the per-value `makePin` a checkbox
|
|
318
|
+
* row over a shared enum slot used to carry, which gave two checkbox rows in
|
|
319
|
+
* one submenu two different pins: one filled when its value was promoted and
|
|
320
|
+
* clearing on a second click, the other filled when the box was ticked and
|
|
321
|
+
* flipping. With `states`, a checkbox row is always the toggle kind.
|
|
322
|
+
*/
|
|
323
|
+
export function makeTogglePin(self, slot,
|
|
324
|
+
// rest-tuple, like `makePin`'s value: a boolean slot may omit the states, and
|
|
325
|
+
// any other slot has to name them, so the type says which without a runtime
|
|
326
|
+
// check that could only fire on a schema widened to `any`
|
|
327
|
+
...states) {
|
|
328
|
+
const current = resolveSlot(self, slot).value;
|
|
329
|
+
const [given] = states;
|
|
330
|
+
if (!given && typeof current !== 'boolean') {
|
|
331
|
+
throw new Error(`cannot build a toggle pin over config slot "${slot}" without naming its on/off states: it resolves to ${JSON.stringify(current)}, not a boolean`);
|
|
332
|
+
}
|
|
333
|
+
const { on, off } = given ?? { on: true, off: false };
|
|
334
|
+
for (const state of [on, off]) {
|
|
335
|
+
if (!isPromotableValue(self.configuration, slot, state)) {
|
|
336
|
+
throw new Error(`cannot toggle config slot "${slot}" to ${JSON.stringify(state)}: the cascade refuses it, so the pin could never apply it`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const active = deepEqual(current, on);
|
|
340
|
+
const onValue = active ? off : on;
|
|
341
|
+
return {
|
|
342
|
+
kind: 'toggle',
|
|
274
343
|
slot,
|
|
275
344
|
onValue,
|
|
276
345
|
active,
|
|
277
346
|
toggle: () => {
|
|
278
|
-
|
|
347
|
+
applyAndOfferDefault(self, slot, onValue);
|
|
279
348
|
},
|
|
280
349
|
};
|
|
281
350
|
}
|
|
@@ -311,9 +380,9 @@ export function getDisplayTypeDefaultChanges(self) {
|
|
|
311
380
|
*
|
|
312
381
|
* **`slots` is required, and an all-slots default is not the convenience it
|
|
313
382
|
* looks like.** It reaches further than any list a dialog can have shown: a
|
|
314
|
-
* promoted default the track *customized* over
|
|
315
|
-
*
|
|
316
|
-
*
|
|
383
|
+
* promoted default the track *customized* over is `inherited: false` and so
|
|
384
|
+
* appears in no row, yet still governs sibling tracks — so clearing it from a
|
|
385
|
+
* dialog that never showed
|
|
317
386
|
* it moves tracks other than the one whose badge was clicked. Clearing every
|
|
318
387
|
* promoted default at once is a preferences-scope action, and Preferences →
|
|
319
388
|
* "Reset to defaults" is where it lives (`clearPreferenceOverrides`).
|
|
@@ -1,55 +1,65 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* the trailing `PushPin`, bundled so the row consumes it as one prop. Built by
|
|
5
|
-
* {@link makePin}.
|
|
2
|
+
* Shared by both pin kinds: which promotable slot the pin writes, whether it
|
|
3
|
+
* draws filled, and the one click it takes.
|
|
6
4
|
*
|
|
7
|
-
* `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* the
|
|
11
|
-
*
|
|
5
|
+
* `slot` is here so a *built menu* can be asked which promotable slots it offers
|
|
6
|
+
* a pin for, which is the only way that question has an answer: declaring
|
|
7
|
+
* `promotedBase` is a schema fact and the pin is a menu fact, and a display that
|
|
8
|
+
* inherits the slot but never builds a row has a slot nothing can ever promote,
|
|
9
|
+
* silently (`promotableSlotsWithoutPin`, guarded by
|
|
10
|
+
* `products/jbrowse-web/src/tests/PromotablePinCoverage.test.ts`).
|
|
12
11
|
*
|
|
13
12
|
* **`toggle` rather than an `apply`/`clear` pair**, which was tried and dropped:
|
|
14
13
|
* the sole renderer is a MUI `ToggleButton` whose `onChange` means exactly
|
|
15
14
|
* "flip", so splitting it adds a member *and* a branch at the one call site that
|
|
16
|
-
* never needed one. `active` is already public for a caller that wants to state
|
|
17
|
-
* direction.
|
|
18
|
-
* actions, where a toggle destroys the ability to set a known state; nothing here
|
|
19
|
-
* stores a value.)
|
|
15
|
+
* never needed one. `active` is already public for a caller that wants to state
|
|
16
|
+
* a direction.
|
|
20
17
|
*
|
|
21
18
|
* Lives here, alone and with no imports, rather than beside `makePin` in
|
|
22
19
|
* `promotableDefaults.ts`: the menu types describe a pin without building one,
|
|
23
|
-
* and `MenuTypes.ts` taking this
|
|
24
|
-
*
|
|
25
|
-
*
|
|
20
|
+
* and `MenuTypes.ts` taking this from that module gave a React-free type file a
|
|
21
|
+
* type closure of 374 files. See `agent-docs/ideas/barrels-block-extraction.md`
|
|
22
|
+
* and `scripts/moduleClosure.ts`.
|
|
26
23
|
*/
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* The promotable slot this pin promotes a value of. Nothing in the UI reads
|
|
30
|
-
* it — a pin renders from `active`, `onValue` and the toggle. It is here so a
|
|
31
|
-
* *built menu* can be asked which promotable slots it offers a pin for, which
|
|
32
|
-
* is the only way that question has an answer: declaring `promotedBase` is a
|
|
33
|
-
* schema fact and the pin is a menu fact, and a display that inherits the slot
|
|
34
|
-
* but never builds a row has a slot nothing can ever promote, silently
|
|
35
|
-
* (`promotableSlotsWithoutPin`, guarded by
|
|
36
|
-
* `products/jbrowse-web/src/tests/PromotablePinCoverage.test.ts`).
|
|
37
|
-
*/
|
|
24
|
+
interface PinBase {
|
|
38
25
|
slot: string;
|
|
39
|
-
/**
|
|
40
|
-
* The value `toggle` promotes — the on-value {@link makePin} was given, or the
|
|
41
|
-
* track's current resolved value for the value-omitted form.
|
|
42
|
-
*
|
|
43
|
-
* `PinAdornment` words itself from this, and has to: a **boolean** on-value
|
|
44
|
-
* promotes a *state*, so a row whose label names the setting rather than a
|
|
45
|
-
* value ("Show legend") gets a pin that promotes hiding the legend as often as
|
|
46
|
-
* showing it. Every other on-value IS what the row's label says — a radio
|
|
47
|
-
* option, a slider's current size — so those keep the value-shaped copy.
|
|
48
|
-
*
|
|
49
|
-
* Required, like `slot`: a pin that cannot say what it promotes is what let
|
|
50
|
-
* that copy state the opposite of what the click does.
|
|
51
|
-
*/
|
|
26
|
+
/** what `toggle` writes into every open track of the display type */
|
|
52
27
|
onValue: unknown;
|
|
53
28
|
active: boolean;
|
|
54
29
|
toggle: () => void;
|
|
55
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* #api core/configuration
|
|
33
|
+
* The pin on a radio or slider row, built by {@link makePin}: `onValue` is the
|
|
34
|
+
* row's own value, `active` means that value is the display type's promoted
|
|
35
|
+
* default, and `toggle` on an outline pin applies the value to every open track
|
|
36
|
+
* and offers it as the default, while on a filled pin it clears that default
|
|
37
|
+
* and touches no track (`applyAndOfferDefault` / `clearDefault`).
|
|
38
|
+
*/
|
|
39
|
+
export interface ValuePin extends PinBase {
|
|
40
|
+
kind: 'value';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* #api core/configuration
|
|
44
|
+
* The pin on a checkbox row, built by {@link makeTogglePin}: the row's own
|
|
45
|
+
* checkbox over every open track of the display type. `active` mirrors the row,
|
|
46
|
+
* `onValue` is the state a click applies (the row's opposite), and `toggle`
|
|
47
|
+
* applies it everywhere and offers it as the default. It never clears a default
|
|
48
|
+
* on its own — promoting the slot's base value is what clears one.
|
|
49
|
+
*/
|
|
50
|
+
export interface TogglePin extends PinBase {
|
|
51
|
+
kind: 'toggle';
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* #api core/configuration
|
|
55
|
+
* The "apply this to every open track of this type" affordance on a menu row —
|
|
56
|
+
* the trailing `PushPin`, bundled so the row consumes it as one prop.
|
|
57
|
+
*
|
|
58
|
+
* `kind` is what the adornment words itself from and what the row builders
|
|
59
|
+
* check: a checkbox row takes a {@link TogglePin}, a radio or slider row a
|
|
60
|
+
* {@link ValuePin}. The two used to be told apart by `typeof onValue ===
|
|
61
|
+
* 'boolean'`, which let a value pin over a boolean slot compile and read as a
|
|
62
|
+
* toggle while clearing on its second click.
|
|
63
|
+
*/
|
|
64
|
+
export type Pin = ValuePin | TogglePin;
|
|
65
|
+
export {};
|
|
@@ -69,7 +69,7 @@ export declare function storedSlotValue(config: AnyConfigurationModel, slot: str
|
|
|
69
69
|
* about a value a caller is about to offer as a pin's on-value.
|
|
70
70
|
*
|
|
71
71
|
* Exists because a pin built over a value the gate refuses is inert in a way
|
|
72
|
-
* nothing reports: `
|
|
72
|
+
* nothing reports: `applyAndOfferDefault` writes it to the session store happily,
|
|
73
73
|
* `resolveSlotIn` then drops it and every track keeps resolving to the tier
|
|
74
74
|
* below, and `isPromotableDefault` compares the *raw* stored value, so the pin
|
|
75
75
|
* draws outline forever while a dead key sits in the user's localStorage. See
|
|
@@ -51,7 +51,7 @@ export function storedSlotValue(config, slot) {
|
|
|
51
51
|
* about a value a caller is about to offer as a pin's on-value.
|
|
52
52
|
*
|
|
53
53
|
* Exists because a pin built over a value the gate refuses is inert in a way
|
|
54
|
-
* nothing reports: `
|
|
54
|
+
* nothing reports: `applyAndOfferDefault` writes it to the session store happily,
|
|
55
55
|
* `resolveSlotIn` then drops it and every track keeps resolving to the tier
|
|
56
56
|
* below, and `isPromotableDefault` compares the *raw* stored value, so the pin
|
|
57
57
|
* draws outline forever while a dead key sits in the user's localStorage. See
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* two slots in the opposite order
|
|
15
15
|
* - `PairwiseIndexedPAFAdapter`'s prose said `<file>.pif.gz.tbi` while its
|
|
16
16
|
* default said `my.paf.gz.tbi`
|
|
17
|
-
* - `PlinkLDTabixAdapter` dropped the
|
|
17
|
+
* - `PlinkLDTabixAdapter`'s description dropped a clause the other eight carried
|
|
18
18
|
* - the placeholder extensions disagreed with each other for no reason
|
|
19
19
|
*
|
|
20
20
|
* The description is written for every tabix adapter rather than naming one
|
|
@@ -39,6 +39,6 @@ export declare const tabixIndexFields: {
|
|
|
39
39
|
readonly uri: '/path/to/my.gz.tbi';
|
|
40
40
|
readonly locationType: 'UriLocation';
|
|
41
41
|
};
|
|
42
|
-
readonly description: 'location of the tabix index. Only needed when it is not named `<file>.tbi`
|
|
42
|
+
readonly description: 'location of the tabix index. Only needed when it is not named `<file>.tbi`, which is what the `uri` shorthand assumes — a `.csi` beside the file is reached with `csi: true` rather than by spelling this out.';
|
|
43
43
|
};
|
|
44
44
|
};
|
|
@@ -15,7 +15,7 @@ import { types } from '@jbrowse/mobx-state-tree';
|
|
|
15
15
|
* two slots in the opposite order
|
|
16
16
|
* - `PairwiseIndexedPAFAdapter`'s prose said `<file>.pif.gz.tbi` while its
|
|
17
17
|
* default said `my.paf.gz.tbi`
|
|
18
|
-
* - `PlinkLDTabixAdapter` dropped the
|
|
18
|
+
* - `PlinkLDTabixAdapter`'s description dropped a clause the other eight carried
|
|
19
19
|
* - the placeholder extensions disagreed with each other for no reason
|
|
20
20
|
*
|
|
21
21
|
* The description is written for every tabix adapter rather than naming one
|
|
@@ -40,6 +40,6 @@ export const tabixIndexFields = {
|
|
|
40
40
|
uri: '/path/to/my.gz.tbi',
|
|
41
41
|
locationType: 'UriLocation',
|
|
42
42
|
},
|
|
43
|
-
description: 'location of the tabix index. Only needed when it is not named `<file>.tbi`
|
|
43
|
+
description: 'location of the tabix index. Only needed when it is not named `<file>.tbi`, which is what the `uri` shorthand assumes — a `.csi` beside the file is reached with `csi: true` rather than by spelling this out.',
|
|
44
44
|
},
|
|
45
45
|
};
|
|
@@ -2,6 +2,7 @@ import { BaseAdapter } from './BaseAdapter.ts';
|
|
|
2
2
|
import type { AnyConfigurationModel } from '../../configuration/index.ts';
|
|
3
3
|
import type { Feature } from '../../util/simpleFeature.ts';
|
|
4
4
|
import type { AugmentedRegion as Region } from '../../util/types/index.ts';
|
|
5
|
+
import type { FeatureDensity } from './featureDensity.ts';
|
|
5
6
|
import type { BaseOptions } from './types.ts';
|
|
6
7
|
import type { Observable } from 'rxjs';
|
|
7
8
|
/**
|
|
@@ -117,6 +118,17 @@ export declare abstract class BaseFeatureDataAdapter<CONF extends AnyConfigurati
|
|
|
117
118
|
* agent-docs/reference/REGION_TOO_LARGE.md.
|
|
118
119
|
*/
|
|
119
120
|
getRegionByteSize(_regions: Region[], _opts?: BaseOptions): Promise<number | undefined>;
|
|
121
|
+
/**
|
|
122
|
+
* Features per bin over each region, at the view's `bpPerPx`, for the density
|
|
123
|
+
* tier the display draws where the region-too-large gate refused the
|
|
124
|
+
* features. The default reads the `densityAdapter` sidecar slot
|
|
125
|
+
* (`densityAdapterConfigSchemaFields`) through `getSubAdapter`; `undefined`
|
|
126
|
+
* means no tier, and the banner stands. ADR-102 records why no index
|
|
127
|
+
* estimate stands in for a missing sidecar.
|
|
128
|
+
*/
|
|
129
|
+
getFeatureDensity(regions: Region[], opts: BaseOptions & {
|
|
130
|
+
bpPerPx: number;
|
|
131
|
+
}): Promise<FeatureDensity[] | undefined>;
|
|
120
132
|
getSources(regions: Region[], opts?: BaseOptions): Promise<{
|
|
121
133
|
name: string;
|
|
122
134
|
color?: string;
|
|
@@ -3,7 +3,9 @@ import { toArray } from 'rxjs/operators';
|
|
|
3
3
|
import { createStatusFanOut } from '../../util/progress.js';
|
|
4
4
|
import { blankStats, scoresToStats } from '../../util/stats.js';
|
|
5
5
|
import { BaseAdapter } from './BaseAdapter.js';
|
|
6
|
+
import { isSubAdapterConfig } from './featureDensity.js';
|
|
6
7
|
import { aggregateQuantitativeStats } from './stats.js';
|
|
8
|
+
import { isFeatureAdapter } from './util.js';
|
|
7
9
|
/**
|
|
8
10
|
* Base class for feature adapters to extend. Defines some methods that
|
|
9
11
|
* subclasses must implement.
|
|
@@ -76,10 +78,7 @@ export class BaseFeatureDataAdapter extends BaseAdapter {
|
|
|
76
78
|
* features over a region, primarily used for quantitative tracks
|
|
77
79
|
*/
|
|
78
80
|
async getRegionQuantitativeStats(region, opts) {
|
|
79
|
-
const feats = this.getFeatures(region,
|
|
80
|
-
...opts,
|
|
81
|
-
statsEstimationMode: true,
|
|
82
|
-
});
|
|
81
|
+
const feats = this.getFeatures(region, opts);
|
|
83
82
|
return scoresToStats(region, feats);
|
|
84
83
|
}
|
|
85
84
|
/**
|
|
@@ -110,6 +109,38 @@ export class BaseFeatureDataAdapter extends BaseAdapter {
|
|
|
110
109
|
async getRegionByteSize(_regions, _opts) {
|
|
111
110
|
return undefined;
|
|
112
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Features per bin over each region, at the view's `bpPerPx`, for the density
|
|
114
|
+
* tier the display draws where the region-too-large gate refused the
|
|
115
|
+
* features. The default reads the `densityAdapter` sidecar slot
|
|
116
|
+
* (`densityAdapterConfigSchemaFields`) through `getSubAdapter`; `undefined`
|
|
117
|
+
* means no tier, and the banner stands. ADR-102 records why no index
|
|
118
|
+
* estimate stands in for a missing sidecar.
|
|
119
|
+
*/
|
|
120
|
+
async getFeatureDensity(regions, opts) {
|
|
121
|
+
const sidecar = this.getConf(['densityAdapter']);
|
|
122
|
+
const resolved = isSubAdapterConfig(sidecar) && this.getSubAdapter
|
|
123
|
+
? (await this.getSubAdapter(sidecar)).dataAdapter
|
|
124
|
+
: undefined;
|
|
125
|
+
if (resolved && !isFeatureAdapter(resolved)) {
|
|
126
|
+
throw new Error(`densityAdapter ${isSubAdapterConfig(sidecar) ? sidecar.type : ''} is not a feature adapter`);
|
|
127
|
+
}
|
|
128
|
+
return resolved
|
|
129
|
+
? Promise.all(regions.map(async (region) => {
|
|
130
|
+
const features = await resolved.getFeaturesArray(region, opts);
|
|
131
|
+
const starts = new Uint32Array(features.length);
|
|
132
|
+
const ends = new Uint32Array(features.length);
|
|
133
|
+
const scores = new Float32Array(features.length);
|
|
134
|
+
features.forEach((feature, i) => {
|
|
135
|
+
const score = feature.get('score');
|
|
136
|
+
starts[i] = feature.get('start');
|
|
137
|
+
ends[i] = feature.get('end');
|
|
138
|
+
scores[i] = score === undefined ? 0 : score;
|
|
139
|
+
});
|
|
140
|
+
return { starts, ends, scores };
|
|
141
|
+
}))
|
|
142
|
+
: undefined;
|
|
143
|
+
}
|
|
113
144
|
async getSources(regions, opts = {}) {
|
|
114
145
|
const features = await this.getFeaturesInMultipleRegionsArray(regions, opts);
|
|
115
146
|
const sources = new Set();
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A density source's intervals over one region, the payload of the density
|
|
3
|
+
* tier that stands in for the features a gated fetch refused: features per bin
|
|
4
|
+
* for a `make-density` sidecar, whatever the bigWig measures otherwise, each
|
|
5
|
+
* value a level over its span so a zoomed read means the same thing. Absolute
|
|
6
|
+
* genomic coordinates.
|
|
7
|
+
*/
|
|
8
|
+
export interface FeatureDensity {
|
|
9
|
+
starts: Uint32Array;
|
|
10
|
+
ends: Uint32Array;
|
|
11
|
+
scores: Float32Array;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The slot a feature adapter spreads to take a density sidecar — a
|
|
15
|
+
* quantitative sub-adapter (typically a BigWig of feature starts per bin) the
|
|
16
|
+
* display reads at the view's bp/px in place of features the region-too-large
|
|
17
|
+
* gate refused. Mirrors MAF's `summaryAdapter`: on the adapter, so the tier
|
|
18
|
+
* names the file it summarizes.
|
|
19
|
+
*/
|
|
20
|
+
export declare const densityAdapterConfigSchemaFields: {
|
|
21
|
+
/**
|
|
22
|
+
* #slot
|
|
23
|
+
*/
|
|
24
|
+
readonly densityAdapter: {
|
|
25
|
+
readonly type: 'frozen';
|
|
26
|
+
readonly defaultValue: null;
|
|
27
|
+
readonly description: 'optional quantitative sub-adapter (e.g. a BigWigAdapter over a features-per-bin bigWig) drawn as a density band where the region is too large to fetch features; null disables it';
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Whether the `densityAdapter` slot holds something a sub-adapter can be built
|
|
32
|
+
* from. Beside the slot because both ends of the tier ask it and they have to
|
|
33
|
+
* agree: the display, deciding the band stands in, and `getFeatureDensity`,
|
|
34
|
+
* resolving the sidecar. They disagreed — the display took any object, the
|
|
35
|
+
* adapter wanted a type — so the shorthand every location slot accepts
|
|
36
|
+
* (`{ uri }`) turned the band on for a read that answered `undefined`, which
|
|
37
|
+
* commits nothing, and the phase then waited on bins no read would ever bring.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isSubAdapterConfig(value: unknown): value is Record<string, unknown> & {
|
|
40
|
+
type: string;
|
|
41
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The slot a feature adapter spreads to take a density sidecar — a
|
|
3
|
+
* quantitative sub-adapter (typically a BigWig of feature starts per bin) the
|
|
4
|
+
* display reads at the view's bp/px in place of features the region-too-large
|
|
5
|
+
* gate refused. Mirrors MAF's `summaryAdapter`: on the adapter, so the tier
|
|
6
|
+
* names the file it summarizes.
|
|
7
|
+
*/
|
|
8
|
+
export const densityAdapterConfigSchemaFields = {
|
|
9
|
+
/**
|
|
10
|
+
* #slot
|
|
11
|
+
*/
|
|
12
|
+
densityAdapter: {
|
|
13
|
+
type: 'frozen',
|
|
14
|
+
defaultValue: null,
|
|
15
|
+
description: 'optional quantitative sub-adapter (e.g. a BigWigAdapter over a features-per-bin bigWig) drawn as a density band where the region is too large to fetch features; null disables it',
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Whether the `densityAdapter` slot holds something a sub-adapter can be built
|
|
20
|
+
* from. Beside the slot because both ends of the tier ask it and they have to
|
|
21
|
+
* agree: the display, deciding the band stands in, and `getFeatureDensity`,
|
|
22
|
+
* resolving the sidecar. They disagreed — the display took any object, the
|
|
23
|
+
* adapter wanted a type — so the shorthand every location slot accepts
|
|
24
|
+
* (`{ uri }`) turned the band on for a read that answered `undefined`, which
|
|
25
|
+
* commits nothing, and the phase then waited on bins no read would ever bring.
|
|
26
|
+
*/
|
|
27
|
+
export function isSubAdapterConfig(value) {
|
|
28
|
+
return (typeof value === 'object' &&
|
|
29
|
+
value !== null &&
|
|
30
|
+
'type' in value &&
|
|
31
|
+
typeof value.type === 'string');
|
|
32
|
+
}
|
|
@@ -3,10 +3,11 @@ import type { AnyConfigurationModel } from '../../configuration/index.ts';
|
|
|
3
3
|
import type { getSubAdapterType } from '../dataAdapterCache.ts';
|
|
4
4
|
import type { AnyDataAdapter } from './util.ts';
|
|
5
5
|
export { type AnyDataAdapter, isFeatureAdapter, isRefNameAliasAdapter, isRegionsAdapter, isSequenceAdapter, isTextSearchAdapter, } from './util.ts';
|
|
6
|
-
export type { BaseOptions,
|
|
6
|
+
export type { BaseOptions, BaseTextSearchArgs, LodTier, SearchType, } from './types.ts';
|
|
7
7
|
export { BaseAdapter } from './BaseAdapter.ts';
|
|
8
8
|
export { cachedSetup } from '../../util/cachedSetup.ts';
|
|
9
9
|
export { BaseFeatureDataAdapter } from './BaseFeatureDataAdapter.ts';
|
|
10
|
+
export { type FeatureDensity, densityAdapterConfigSchemaFields, isSubAdapterConfig, } from './featureDensity.ts';
|
|
10
11
|
export { BaseSequenceAdapter } from './BaseSequenceAdapter.ts';
|
|
11
12
|
export type { BaseTextSearchAdapter } from './BaseTextSearchAdapter.ts';
|
|
12
13
|
export type { Alias, BaseRefNameAliasAdapter, } from './BaseRefNameAliasAdapter.ts';
|
|
@@ -2,4 +2,5 @@ export { isFeatureAdapter, isRefNameAliasAdapter, isRegionsAdapter, isSequenceAd
|
|
|
2
2
|
export { BaseAdapter } from './BaseAdapter.js';
|
|
3
3
|
export { cachedSetup } from '../../util/cachedSetup.js';
|
|
4
4
|
export { BaseFeatureDataAdapter } from './BaseFeatureDataAdapter.js';
|
|
5
|
+
export { densityAdapterConfigSchemaFields, isSubAdapterConfig, } from './featureDensity.js';
|
|
5
6
|
export { BaseSequenceAdapter } from './BaseSequenceAdapter.js';
|
|
@@ -3,8 +3,40 @@ import type { RectifiedQuantitativeStats } from '../../util/stats.ts';
|
|
|
3
3
|
import type { AugmentedRegion as Region } from '../../util/types/index.ts';
|
|
4
4
|
import type { BaseOptions } from './types.ts';
|
|
5
5
|
import type { Observable } from 'rxjs';
|
|
6
|
+
/**
|
|
7
|
+
* What a caller that will *judge* the density knows and the probe does not: how
|
|
8
|
+
* wide a window has to be before its count can settle that judgement, and when
|
|
9
|
+
* a count has settled it. Supplying it turns the ladder below from "grow until
|
|
10
|
+
* the estimate is precise" into "grow until the verdict is decided", which at
|
|
11
|
+
* whole-genome zoom is one window instead of thirteen.
|
|
12
|
+
*
|
|
13
|
+
* The probe stays ignorant of what the budget means — `plugins/canvas`'s
|
|
14
|
+
* `densityProbeGate` owns both numbers, so the comparison that refuses a region
|
|
15
|
+
* lives beside the one the banner re-derives rather than in a second copy here.
|
|
16
|
+
*/
|
|
17
|
+
export interface DensityProbeGate {
|
|
18
|
+
/** First window to sample: the narrowest one whose count can settle it. */
|
|
19
|
+
initialInterval: number;
|
|
20
|
+
/** Whether this many admitted features in this many bp decides the verdict. */
|
|
21
|
+
settled: (admitted: number, sampledBp: number) => boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The adapter options a probe forwards, plus the two things only its caller
|
|
25
|
+
* knows. Named rather than trailing positionals: `BaseOptions` has no required
|
|
26
|
+
* member, so every one of its slots structurally accepts anything, and an
|
|
27
|
+
* `admit` handed to the `opts` slot typechecks and then never filters.
|
|
28
|
+
*/
|
|
29
|
+
export interface DensityProbeOptions extends BaseOptions {
|
|
30
|
+
/**
|
|
31
|
+
* The caller's feature-admission predicate (config filters, type gates, ...).
|
|
32
|
+
* See the note on the growth/report asymmetry below.
|
|
33
|
+
*/
|
|
34
|
+
admit?: (feature: Feature) => boolean;
|
|
35
|
+
/** Stop as soon as the verdict is decided rather than when it is precise. */
|
|
36
|
+
gate?: DensityProbeGate;
|
|
37
|
+
}
|
|
6
38
|
export declare function aggregateQuantitativeStats(stats: RectifiedQuantitativeStats[]): RectifiedQuantitativeStats;
|
|
7
|
-
export declare function calculateFeatureDensityStats(region: Region, getFeatures: (region: Region, opts?: BaseOptions) => Observable<Feature>,
|
|
39
|
+
export declare function calculateFeatureDensityStats(region: Region, getFeatures: (region: Region, opts?: BaseOptions) => Observable<Feature>, { admit, gate, ...opts }?: DensityProbeOptions): Promise<{
|
|
8
40
|
featureDensity: number;
|
|
9
41
|
}>;
|
|
10
42
|
export { blankStats } from '../../util/stats.ts';
|