@jbrowse/plugin-linear-genome-view 5.0.0-beta.18 → 5.0.0-beta.19
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/LinearGenomeView/components/ImportForm.js +2 -4
- package/esm/LinearGenomeView/components/LinearGenomeViewContainer.js +1 -1
- package/esm/LinearGenomeView/components/SearchBox.js +1 -9
- package/esm/LinearGenomeView/components/SearchResultsDialog.js +1 -1
- package/esm/LinearGenomeView/components/SearchResultsTable.d.ts +2 -1
- package/esm/LinearGenomeView/components/SearchResultsTable.js +23 -5
- package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlight.js +2 -3
- package/esm/LinearGenomeView/components/TrackContainer.d.ts +2 -3
- package/esm/LinearGenomeView/components/TrackContainer.js +3 -4
- package/esm/LinearGenomeView/components/TrackLabelRefNameWarning.d.ts +3 -4
- package/esm/LinearGenomeView/components/TrackLabelRefNameWarning.js +23 -10
- package/esm/LinearGenomeView/components/TrackRenderingContainer.d.ts +2 -3
- package/esm/LinearGenomeView/components/TrackRenderingContainer.js +1 -1
- package/esm/LinearGenomeView/index.d.ts +1 -1
- package/esm/LinearGenomeView/index.js +2 -0
- package/esm/LinearGenomeView/keyboardHandler.d.ts +8 -9
- package/esm/LinearGenomeView/keyboardHandler.js +58 -34
- package/esm/LinearGenomeView/menuItems.js +3 -2
- package/esm/LinearGenomeView/model.d.ts +412 -45
- package/esm/LinearGenomeView/model.js +23 -15
- package/esm/LinearGenomeView/rExport/exportLinearView.js +4 -5
- package/esm/LinearGenomeView/rExport/rScript.d.ts +5 -1
- package/esm/LinearGenomeView/rExport/rScript.js +24 -3
- package/esm/LinearGenomeView/showRegionsWithUndo.d.ts +1 -1
- package/esm/LinearGenomeView/showRegionsWithUndo.js +1 -1
- package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +3 -1
- package/esm/LinearGenomeView/util.d.ts +1 -1
- package/esm/LinearGenomeView/util.js +1 -1
- package/esm/displayKitTests/perRegionTestEnv.d.ts +10 -4
- package/esm/index.js +0 -2
- package/esm/searchUtils.d.ts +14 -2
- package/esm/searchUtils.js +56 -36
- package/package.json +9 -9
- package/esm/FeatureTrack/configSchema.d.ts +0 -219
- package/esm/FeatureTrack/configSchema.js +0 -57
- package/esm/FeatureTrack/index.d.ts +0 -2
- package/esm/FeatureTrack/index.js +0 -13
|
@@ -2,7 +2,8 @@ import { canonicalLocString } from '@jbrowse/core/TextSearch/places';
|
|
|
2
2
|
import { getConf, readConfObject } from '@jbrowse/core/configuration';
|
|
3
3
|
import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes/models';
|
|
4
4
|
import { exportViewSvg } from '@jbrowse/core/svg/exportViewSvg';
|
|
5
|
-
import {
|
|
5
|
+
import { highlightListMenuItems } from '@jbrowse/core/ui/menuItems';
|
|
6
|
+
import { assembleLocString, clamp, getBpDisplayStr, getEnv, getNotificationSink, getSession, isSessionModelWithWidgets, localStorageGetBoolean, localStorageGetItem, localStorageSetBoolean, localStorageSetItem, springAnimate, sum, } from '@jbrowse/core/util';
|
|
6
7
|
import { bpToLinearBp, bpToPx, computeMoveToLayout, createOverviewLayout, getLayoutHighlightCoords, getOverviewRegionPxSpan, moveTo, pxToBp, } from '@jbrowse/core/util/Base1DUtils';
|
|
7
8
|
import { scaleBandHeights } from '@jbrowse/core/util/bandHeight';
|
|
8
9
|
import { wholeBaseRegions } from '@jbrowse/core/util/blockTypes';
|
|
@@ -297,11 +298,11 @@ export function stateModelFactory(pluginManager) {
|
|
|
297
298
|
hideNoTracksActive: types.stripDefault(types.boolean, false),
|
|
298
299
|
/**
|
|
299
300
|
* #property
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
301
|
+
* ignored: the hierarchical selector is the only one. Declared because
|
|
302
|
+
* saved sessions and share links carry it.
|
|
303
|
+
* @deprecated
|
|
303
304
|
*/
|
|
304
|
-
trackSelectorType: types.stripDefault(types.
|
|
305
|
+
trackSelectorType: types.stripDefault(types.string, 'hierarchical'),
|
|
305
306
|
/**
|
|
306
307
|
* #property
|
|
307
308
|
* show the "center line". A personal preference: never in a session
|
|
@@ -1332,12 +1333,10 @@ export function stateModelFactory(pluginManager) {
|
|
|
1332
1333
|
if (!assemblyName) {
|
|
1333
1334
|
throw new Error('the view has no assembly to search yet');
|
|
1334
1335
|
}
|
|
1335
|
-
const { assemblyManager, textSearchManager } = getSession(self);
|
|
1336
1336
|
const results = await fetchResults({
|
|
1337
|
+
session: getSession(self),
|
|
1337
1338
|
queryString: query,
|
|
1338
1339
|
assemblyName,
|
|
1339
|
-
textSearchManager,
|
|
1340
|
-
assembly: await assemblyManager.waitForAssembly(assemblyName),
|
|
1341
1340
|
signal: opts?.signal,
|
|
1342
1341
|
});
|
|
1343
1342
|
return searchHitsOf(self, results, query, assemblyName, result => navToOption({
|
|
@@ -2249,7 +2248,7 @@ export function stateModelFactory(pluginManager) {
|
|
|
2249
2248
|
*
|
|
2250
2249
|
* The coarse blocks are a 500ms throttle, and every consumer trades
|
|
2251
2250
|
* freshness for not recomputing per animation frame — the location box,
|
|
2252
|
-
*
|
|
2251
|
+
* the feature display's on-screen feature set, and the two per-bp scans behind
|
|
2253
2252
|
* `settledDynamicBlocks`. That trade is only sound while the answer is a
|
|
2254
2253
|
* few frames old. **A jump makes it unrelated instead**, because there is
|
|
2255
2254
|
* nothing to coalesce: the viewport left behind is not an approximation of
|
|
@@ -2710,16 +2709,26 @@ export function stateModelFactory(pluginManager) {
|
|
|
2710
2709
|
getSession(self).addHighlight(region);
|
|
2711
2710
|
}
|
|
2712
2711
|
},
|
|
2712
|
+
/**
|
|
2713
|
+
* #action
|
|
2714
|
+
* navigates to a highlight, zoomed out a little for context. Goes through
|
|
2715
|
+
* a locstring so it reaches a refName the view is not displaying
|
|
2716
|
+
*/
|
|
2717
|
+
navToHighlight(highlight) {
|
|
2718
|
+
const { assemblyName, ...region } = highlight;
|
|
2719
|
+
return self.navToLocString(assembleLocString(region), assemblyName, 0.2);
|
|
2720
|
+
},
|
|
2721
|
+
}))
|
|
2722
|
+
.actions(self => ({
|
|
2713
2723
|
/**
|
|
2714
2724
|
* #action
|
|
2715
2725
|
* navigates to the most recently added highlight on this view's
|
|
2716
|
-
* assemblies
|
|
2726
|
+
* assemblies
|
|
2717
2727
|
*/
|
|
2718
2728
|
async navigateNewestHighlight() {
|
|
2719
2729
|
const newest = self.highlights.at(-1);
|
|
2720
2730
|
if (newest) {
|
|
2721
|
-
|
|
2722
|
-
await self.navToLocString(assembleLocString(region), assemblyName, 0.2);
|
|
2731
|
+
await self.navToHighlight(newest);
|
|
2723
2732
|
}
|
|
2724
2733
|
else {
|
|
2725
2734
|
getSession(self).notify('There are no highlights to navigate to.', 'info');
|
|
@@ -2830,11 +2839,10 @@ export function stateModelFactory(pluginManager) {
|
|
|
2830
2839
|
},
|
|
2831
2840
|
/**
|
|
2832
2841
|
* #method
|
|
2833
|
-
*
|
|
2834
|
-
* this via Core-extendPluggableElement to add items
|
|
2842
|
+
* a highlight chip's menu rows after Dismiss; extend this to add one
|
|
2835
2843
|
*/
|
|
2836
2844
|
highlightMenuItems(_highlight) {
|
|
2837
|
-
return
|
|
2845
|
+
return highlightListMenuItems(getSession(self), getEnv(self).pluginManager);
|
|
2838
2846
|
},
|
|
2839
2847
|
}))
|
|
2840
2848
|
.actions(self => {
|
|
@@ -2,9 +2,6 @@ import { fullConfSnapshot, readConfObject } from '@jbrowse/core/configuration';
|
|
|
2
2
|
import { getSession } from '@jbrowse/core/util';
|
|
3
3
|
import { getSnapshot } from '@jbrowse/mobx-state-tree';
|
|
4
4
|
import { exportTracksToR } from './rScript.js';
|
|
5
|
-
function trackConf(track) {
|
|
6
|
-
return track.configuration;
|
|
7
|
-
}
|
|
8
5
|
/** The regions on screen, each displayed region cut to what the view shows of it. */
|
|
9
6
|
function viewRegions(view) {
|
|
10
7
|
const blocks = view.dynamicBlocks.contentBlocks;
|
|
@@ -52,10 +49,10 @@ function tracksOf(view) {
|
|
|
52
49
|
const { heightMode, height } = fullConfSnapshot(display.configuration);
|
|
53
50
|
tracks.push({
|
|
54
51
|
trackId: track.configuration.trackId,
|
|
55
|
-
trackName: readConfObject(
|
|
52
|
+
trackName: readConfObject(track.configuration, 'name') ||
|
|
56
53
|
track.configuration.trackId,
|
|
57
54
|
displayType: display.type,
|
|
58
|
-
adapter: readConfObject(
|
|
55
|
+
adapter: readConfObject(track.configuration, 'adapter'),
|
|
59
56
|
display: written,
|
|
60
57
|
heightMode,
|
|
61
58
|
height,
|
|
@@ -71,6 +68,8 @@ export function exportLinearViewToR(view, out) {
|
|
|
71
68
|
regions: viewRegions(view),
|
|
72
69
|
assembly: assemblyOf(view),
|
|
73
70
|
bpPerPx: view.bpPerPx,
|
|
71
|
+
colorByFrame: view.colorByFrame,
|
|
72
|
+
showAminoAcids: view.showAminoAcids,
|
|
74
73
|
out,
|
|
75
74
|
notes: view.displayedRegions.some(r => r.reversed)
|
|
76
75
|
? ['view: shown right to left, where the figure runs left to right']
|
|
@@ -75,13 +75,17 @@ export declare function locusOf(refName: string, start: number, end: number): st
|
|
|
75
75
|
* header instead of stopping the figure: a script that quietly differs from
|
|
76
76
|
* its view says so.
|
|
77
77
|
*/
|
|
78
|
-
export declare function exportTracksToR({ tracks, regions, assembly: assemblySnapshot, bpPerPx, out, notes: viewNotes, }: {
|
|
78
|
+
export declare function exportTracksToR({ tracks, regions, assembly: assemblySnapshot, bpPerPx, colorByFrame, showAminoAcids, out, notes: viewNotes, }: {
|
|
79
79
|
tracks: readonly RExportTrack[];
|
|
80
80
|
regions: readonly Region[];
|
|
81
81
|
/** The view's assembly config as written, which names its sequence and its contigs' aliases. */
|
|
82
82
|
assembly?: Record<string, unknown>;
|
|
83
83
|
/** The view's zoom, which decides what a feature or quantitative display shows. */
|
|
84
84
|
bpPerPx?: number;
|
|
85
|
+
/** The view's "CDS reading frame colors", which a feature track takes. */
|
|
86
|
+
colorByFrame?: boolean;
|
|
87
|
+
/** The view's "Amino acids when zoomed in", which a feature track takes. */
|
|
88
|
+
showAminoAcids?: boolean;
|
|
85
89
|
out?: string;
|
|
86
90
|
/** What the caller knows of the view that the figure does not show. */
|
|
87
91
|
notes?: readonly string[];
|
|
@@ -93,9 +93,15 @@ const RESERVED = new Set([
|
|
|
93
93
|
'Inf',
|
|
94
94
|
'NaN',
|
|
95
95
|
'NA',
|
|
96
|
+
'NA_integer_',
|
|
97
|
+
'NA_real_',
|
|
98
|
+
'NA_complex_',
|
|
99
|
+
'NA_character_',
|
|
96
100
|
]);
|
|
97
101
|
function isIdentifier(s) {
|
|
98
|
-
return /^[A-Za-z
|
|
102
|
+
return (/^([A-Za-z]|\.(?!\d))[A-Za-z0-9._]*$/.test(s) &&
|
|
103
|
+
!/^(\.\.\.|\.\.\d+)$/.test(s) &&
|
|
104
|
+
!RESERVED.has(s));
|
|
99
105
|
}
|
|
100
106
|
/**
|
|
101
107
|
* A config value as the R literal ggjbrowse hands the engine: a `list` per
|
|
@@ -328,6 +334,16 @@ function trackNames(tracks) {
|
|
|
328
334
|
return name;
|
|
329
335
|
});
|
|
330
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* A track's `jbrowse_stack()` argument, named as the view labels it so its
|
|
339
|
+
* band is titled. A name `width` would set the stack's own `width`, so that
|
|
340
|
+
* one goes in a list, whose names title its tracks too.
|
|
341
|
+
*/
|
|
342
|
+
function stackArgument(title, name) {
|
|
343
|
+
return title === 'width'
|
|
344
|
+
? `list(width = ${name})`
|
|
345
|
+
: `${isIdentifier(title) ? title : rStr(title)} = ${name}`;
|
|
346
|
+
}
|
|
331
347
|
/** What the figure cannot show of a track whose settings ggjbrowse reads. */
|
|
332
348
|
function settingNotes(track) {
|
|
333
349
|
const { color } = track.display.encoding ?? {};
|
|
@@ -346,7 +362,7 @@ function settingNotes(track) {
|
|
|
346
362
|
* header instead of stopping the figure: a script that quietly differs from
|
|
347
363
|
* its view says so.
|
|
348
364
|
*/
|
|
349
|
-
export function exportTracksToR({ tracks, regions, assembly: assemblySnapshot, bpPerPx, out = 'figure.png', notes: viewNotes = [], }) {
|
|
365
|
+
export function exportTracksToR({ tracks, regions, assembly: assemblySnapshot, bpPerPx, colorByFrame = false, showAminoAcids = true, out = 'figure.png', notes: viewNotes = [], }) {
|
|
350
366
|
const notes = [...viewNotes];
|
|
351
367
|
const assembly = assemblySnapshot && assemblyArgument(assemblySnapshot);
|
|
352
368
|
if (assembly && 'skipped' in assembly) {
|
|
@@ -360,6 +376,7 @@ export function exportTracksToR({ tracks, regions, assembly: assemblySnapshot, b
|
|
|
360
376
|
const names = trackNames(tracks);
|
|
361
377
|
const reads = [];
|
|
362
378
|
const drawn = [];
|
|
379
|
+
const bands = [];
|
|
363
380
|
let alignments;
|
|
364
381
|
tracks.forEach((track, i) => {
|
|
365
382
|
const reader = READERS[track.displayType];
|
|
@@ -381,10 +398,13 @@ export function exportTracksToR({ tracks, regions, assembly: assemblySnapshot, b
|
|
|
381
398
|
}
|
|
382
399
|
: track.display;
|
|
383
400
|
const width = viewPx !== undefined;
|
|
401
|
+
const geneTrack = track.displayType === 'LinearBasicDisplay';
|
|
384
402
|
const args = [
|
|
385
403
|
...(Object.keys(display).length ? [`display = ${rValue(display)}`] : []),
|
|
386
404
|
...(width ? ['width = width'] : []),
|
|
387
405
|
...(assemblyValue ? ['assembly = assembly'] : []),
|
|
406
|
+
...(geneTrack && colorByFrame ? ['color_by_cds = TRUE'] : []),
|
|
407
|
+
...(geneTrack && !showAminoAcids ? ['amino_acids = FALSE'] : []),
|
|
388
408
|
...(source.index ? [`index = ${rStr(source.index)}`] : []),
|
|
389
409
|
];
|
|
390
410
|
const name = names[i];
|
|
@@ -397,6 +417,7 @@ export function exportTracksToR({ tracks, regions, assembly: assemblySnapshot, b
|
|
|
397
417
|
` ${['locus', ...args].join(',\n ')})`,
|
|
398
418
|
].join('\n'));
|
|
399
419
|
drawn.push(name);
|
|
420
|
+
bands.push(stackArgument(track.trackName, name));
|
|
400
421
|
if (reader.call === 'jbrowse_alignments') {
|
|
401
422
|
alignments ??= name;
|
|
402
423
|
}
|
|
@@ -456,7 +477,7 @@ export function exportTracksToR({ tracks, regions, assembly: assemblySnapshot, b
|
|
|
456
477
|
'',
|
|
457
478
|
reads.join('\n\n'),
|
|
458
479
|
'',
|
|
459
|
-
`fig <- jbrowse_stack(${
|
|
480
|
+
`fig <- jbrowse_stack(${bands.join(',\n ')})`,
|
|
460
481
|
'print(fig)',
|
|
461
482
|
`ggplot2::ggsave(${rStr(out)}, fig, width = jbrowse_width(fig), height = jbrowse_height(fig))`,
|
|
462
483
|
'',
|
|
@@ -6,7 +6,7 @@ import type { Region } from '@jbrowse/core/util/types';
|
|
|
6
6
|
*
|
|
7
7
|
* This is the "navigate the view you are looking at" half of a launcher, as
|
|
8
8
|
* against `session.addView`, which opens a second one. Two features do it —
|
|
9
|
-
* plugin-
|
|
9
|
+
* plugin-features's collapsed introns and plugin-alignments' "view mate region" —
|
|
10
10
|
* and both had their own copy of the same fifteen lines, including the same two
|
|
11
11
|
* decisions worth stating once:
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@ import { transaction } from 'mobx';
|
|
|
6
6
|
*
|
|
7
7
|
* This is the "navigate the view you are looking at" half of a launcher, as
|
|
8
8
|
* against `session.addView`, which opens a second one. Two features do it —
|
|
9
|
-
* plugin-
|
|
9
|
+
* plugin-features's collapsed introns and plugin-alignments' "view mate region" —
|
|
10
10
|
* and both had their own copy of the same fifteen lines, including the same two
|
|
11
11
|
* decisions worth stating once:
|
|
12
12
|
*
|
|
@@ -39,7 +39,9 @@ export async function renderToSvg(model, opts) {
|
|
|
39
39
|
textHeight,
|
|
40
40
|
trackLabels,
|
|
41
41
|
});
|
|
42
|
-
|
|
42
|
+
if (opts.announceSkipped !== false) {
|
|
43
|
+
notifySkippedSvgTracks(session, skippedTracks);
|
|
44
|
+
}
|
|
43
45
|
// read after the displays' waits, and handed to SVGHeader rather than read
|
|
44
46
|
// again, so the reserved `tracksTop` and the drawn header are one layout
|
|
45
47
|
const { width, effectiveShowCytobands } = model;
|
|
@@ -25,7 +25,7 @@ interface CenterKeepingView {
|
|
|
25
25
|
* A caller building a view SNAPSHOT does: it has no model to call
|
|
26
26
|
* `fitAllRegions()` on, and naming `bpPerPx`/`offsetPx` instead is dropped
|
|
27
27
|
* whenever the snapshot also carries a `windowWidthBp` — which one copied off an
|
|
28
|
-
* existing view always does. plugin-
|
|
28
|
+
* existing view always does. plugin-features's collapsed-intron launch is that
|
|
29
29
|
* caller. A live view calls `fitAllRegions()`.
|
|
30
30
|
*
|
|
31
31
|
* `width` enters only through the zoom-in floor, which bites for a region set
|
|
@@ -18,7 +18,7 @@ import { tickLabelsWorthDrawing } from '@jbrowse/core/util/tickLabels';
|
|
|
18
18
|
* A caller building a view SNAPSHOT does: it has no model to call
|
|
19
19
|
* `fitAllRegions()` on, and naming `bpPerPx`/`offsetPx` instead is dropped
|
|
20
20
|
* whenever the snapshot also carries a `windowWidthBp` — which one copied off an
|
|
21
|
-
* existing view always does. plugin-
|
|
21
|
+
* existing view always does. plugin-features's collapsed-intron launch is that
|
|
22
22
|
* caller. A live view calls `fitAllRegions()`.
|
|
23
23
|
*
|
|
24
24
|
* `width` enters only through the zoom-in floor, which bites for a region set
|
|
@@ -31,7 +31,7 @@ export interface PerRegionTestControl {
|
|
|
31
31
|
*/
|
|
32
32
|
estimateBytes: number;
|
|
33
33
|
estimateCalls: number;
|
|
34
|
-
/** the display's own density verdict,
|
|
34
|
+
/** the display's own density verdict, the feature display's second too-large axis */
|
|
35
35
|
densityTooLarge: boolean;
|
|
36
36
|
/**
|
|
37
37
|
* What the next fetch stores, so a test can tell the payload a refetch
|
|
@@ -45,7 +45,7 @@ export interface PerRegionTestControl {
|
|
|
45
45
|
* displays compose this foundation, and every one of them adds a plugin's worth
|
|
46
46
|
* of behavior on top — so a test that boots one is testing that plugin as much
|
|
47
47
|
* as the foundation, which is how the foundation's own autoruns came to be
|
|
48
|
-
* pinned only by
|
|
48
|
+
* pinned only by the feature display's suite.
|
|
49
49
|
*/
|
|
50
50
|
/** Which of the gate's opt-in hooks this display overrides. */
|
|
51
51
|
export interface GateOptIns {
|
|
@@ -266,7 +266,9 @@ declare function makeStateModel(control: PerRegionTestControl, gate: GateOptIns,
|
|
|
266
266
|
readonly plotKeys: string[];
|
|
267
267
|
readonly plot: import("@jbrowse/core/configuration").Plot;
|
|
268
268
|
readonly configNotices: string[];
|
|
269
|
+
} & {
|
|
269
270
|
readonly notices: string[];
|
|
271
|
+
} & {
|
|
270
272
|
readonly cornerNotices: string[];
|
|
271
273
|
readonly plotExamples: readonly import("@jbrowse/core/configuration").PlotExample[];
|
|
272
274
|
readonly configDocsUrl: string;
|
|
@@ -498,12 +500,12 @@ export declare function createPerRegionTestEnvironment({ measuresBytes, gate, es
|
|
|
498
500
|
*/
|
|
499
501
|
estimateBytes?: number;
|
|
500
502
|
}): {
|
|
501
|
-
createDisplay: (
|
|
503
|
+
createDisplay: (args_0?: {
|
|
502
504
|
displayedRegions?: import("@jbrowse/core/util").Region[];
|
|
503
505
|
displaySnapshot?: Record<string, unknown>;
|
|
504
506
|
skipWidth?: boolean;
|
|
505
507
|
regionsInSnapshot?: boolean;
|
|
506
|
-
}) => {
|
|
508
|
+
} | undefined) => {
|
|
507
509
|
session: import("@jbrowse/mobx-state-tree").ModelInstanceTypeProps<{
|
|
508
510
|
name: import("@jbrowse/mobx-state-tree").IType<string | undefined, string, string>;
|
|
509
511
|
view: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").IAnyModelType>;
|
|
@@ -804,7 +806,9 @@ export declare function createPerRegionTestEnvironment({ measuresBytes, gate, es
|
|
|
804
806
|
readonly plotKeys: string[];
|
|
805
807
|
readonly plot: import("@jbrowse/core/configuration").Plot;
|
|
806
808
|
readonly configNotices: string[];
|
|
809
|
+
} & {
|
|
807
810
|
readonly notices: string[];
|
|
811
|
+
} & {
|
|
808
812
|
readonly cornerNotices: string[];
|
|
809
813
|
readonly plotExamples: readonly import("@jbrowse/core/configuration").PlotExample[];
|
|
810
814
|
readonly configDocsUrl: string;
|
|
@@ -1231,7 +1235,9 @@ export declare function createPerRegionTestEnvironment({ measuresBytes, gate, es
|
|
|
1231
1235
|
readonly plotKeys: string[];
|
|
1232
1236
|
readonly plot: import("@jbrowse/core/configuration").Plot;
|
|
1233
1237
|
readonly configNotices: string[];
|
|
1238
|
+
} & {
|
|
1234
1239
|
readonly notices: string[];
|
|
1240
|
+
} & {
|
|
1235
1241
|
readonly cornerNotices: string[];
|
|
1236
1242
|
readonly plotExamples: readonly import("@jbrowse/core/configuration").PlotExample[];
|
|
1237
1243
|
readonly configDocsUrl: string;
|
package/esm/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import { isAbstractMenuManager } from '@jbrowse/core/util';
|
|
|
4
4
|
import { VIEW_TRACK_LABEL_MODES } from '@jbrowse/display-kit/types';
|
|
5
5
|
import { types } from '@jbrowse/mobx-state-tree';
|
|
6
6
|
import LineStyleIcon from '@mui/icons-material/LineStyle';
|
|
7
|
-
import FeatureTrackF from './FeatureTrack/index.js';
|
|
8
7
|
import LaunchLinearGenomeViewF from './LaunchLinearGenomeView/index.js';
|
|
9
8
|
import SequenceFeatureHoverHighlightExtensionF from './LinearGenomeView/components/SequenceFeatureHoverHighlightExtension.js';
|
|
10
9
|
import LinearGenomeViewF from './LinearGenomeView/index.js';
|
|
@@ -33,7 +32,6 @@ export default class LinearGenomeViewPlugin extends Plugin {
|
|
|
33
32
|
},
|
|
34
33
|
});
|
|
35
34
|
install(pluginManager) {
|
|
36
|
-
FeatureTrackF(pluginManager);
|
|
37
35
|
LinearGenomeViewF(pluginManager);
|
|
38
36
|
LaunchLinearGenomeViewF(pluginManager);
|
|
39
37
|
SequenceFeatureHoverHighlightExtensionF(pluginManager);
|
package/esm/searchUtils.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type BaseResult from '@jbrowse/core/TextSearch/BaseResults';
|
|
|
3
3
|
import type TextSearchManager from '@jbrowse/core/TextSearch/TextSearchManager';
|
|
4
4
|
import type { Assembly } from '@jbrowse/core/assemblyManager/assembly';
|
|
5
5
|
import type { SearchType } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
6
|
-
import type { AssemblyHost, NotificationSink, TrackCatalog } from '@jbrowse/core/util';
|
|
6
|
+
import type { AbstractSessionModel, AssemblyHost, NotificationSink, TrackCatalog } from '@jbrowse/core/util';
|
|
7
7
|
declare module '@jbrowse/core/PluginManager' {
|
|
8
8
|
interface ExtensionPointRegistry {
|
|
9
9
|
'LinearGenomeView-searchResultSelected': {
|
|
@@ -67,7 +67,19 @@ interface SearchArgs {
|
|
|
67
67
|
assembly?: Assembly;
|
|
68
68
|
signal?: AbortSignal;
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
interface SessionSearchArgs {
|
|
71
|
+
session: Pick<AbstractSessionModel, 'assemblyManager' | 'textSearchManager'>;
|
|
72
|
+
queryString: string;
|
|
73
|
+
assemblyName: string;
|
|
74
|
+
searchType?: SearchType;
|
|
75
|
+
signal?: AbortSignal;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The search box's hits for a query: refNames and text-index results, merged.
|
|
79
|
+
* Pass the session and the function finds the index manager and the assembly
|
|
80
|
+
* itself; passing `textSearchManager` and `assembly` is the older form.
|
|
81
|
+
*/
|
|
82
|
+
export declare function fetchResults(args: SessionSearchArgs | SearchArgs): Promise<BaseResult[]>;
|
|
71
83
|
export declare function nameNotFound(input: string, assemblyName: string, { indexCount, failures }: {
|
|
72
84
|
indexCount: number;
|
|
73
85
|
failures: unknown[];
|
package/esm/searchUtils.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { RefSequenceResult } from '@jbrowse/core/TextSearch/BaseResults';
|
|
2
|
-
import { groupByPlace } from '@jbrowse/core/TextSearch/places';
|
|
3
|
-
import { dedupe, getEnv, getNotificationSink, getSession, matchRefNames, MAX_GLOB_REGIONS, UnknownRefNameError, } from '@jbrowse/core/util';
|
|
2
|
+
import { groupByPlace, landsInAssembly } from '@jbrowse/core/TextSearch/places';
|
|
3
|
+
import { dedupe, getEnv, getNotificationSink, getSession, matchRefNames, MAX_GLOB_REGIONS, rankRefNames, UnknownRefNameError, } from '@jbrowse/core/util';
|
|
4
4
|
import { isAlive } from '@jbrowse/mobx-state-tree';
|
|
5
5
|
import { parseLocStrings } from './LinearGenomeView/util.js';
|
|
6
6
|
// Budget for refName suggestions from a query. Deliberately far below the
|
|
7
|
-
// autocomplete's ~100-row display cap:
|
|
8
|
-
// search hits, so a scaffold-heavy assembly would otherwise fill every row with
|
|
7
|
+
// autocomplete's ~100-row display cap: exact and prefix refName hits are
|
|
8
|
+
// returned ahead of the text search hits, so a scaffold-heavy assembly would otherwise fill every row with
|
|
9
9
|
// scaffolds and push the gene hits out of the list entirely. Raising this to
|
|
10
10
|
// match the display cap looks like a consistency fix and is not one.
|
|
11
11
|
const MAX_REFNAME_HITS = 10;
|
|
@@ -274,16 +274,20 @@ export async function handleSelectedRegion({ input, model, assemblyName, grow, s
|
|
|
274
274
|
}
|
|
275
275
|
else {
|
|
276
276
|
// no search hits: still try to resolve the input as a locstring (bare
|
|
277
|
-
// refname, "ref start end" triplet, etc).
|
|
278
|
-
// refname
|
|
279
|
-
//
|
|
280
|
-
// error for coordinate
|
|
277
|
+
// refname, "ref start end" triplet, etc). If that also can't find a
|
|
278
|
+
// refname and the input names no sequence and no coordinate — a gene
|
|
279
|
+
// name, or a phrase like "breast cancer" — reframe the unknown-ref error
|
|
280
|
+
// as a name miss; keep the specific ref error for coordinate-shaped input
|
|
281
281
|
try {
|
|
282
282
|
await navToLocstrings();
|
|
283
283
|
return true;
|
|
284
284
|
}
|
|
285
285
|
catch (e) {
|
|
286
|
-
const isPlainName = !input.includes(':') &&
|
|
286
|
+
const isPlainName = !input.includes(':') &&
|
|
287
|
+
input
|
|
288
|
+
.trim()
|
|
289
|
+
.split(/\s+/)
|
|
290
|
+
.every(token => !isRef(token) && !/^\d[\d,]*$/.test(token));
|
|
287
291
|
if (e instanceof UnknownRefNameError && isPlainName) {
|
|
288
292
|
throw nameNotFound(input, assemblyName, found);
|
|
289
293
|
}
|
|
@@ -308,17 +312,39 @@ async function searchNames({ queryString, searchType, assemblyName, textSearchMa
|
|
|
308
312
|
// not itself kick off the lazy load. A load failure just leaves allRefNames
|
|
309
313
|
// undefined, so this still returns whatever the text search turned up
|
|
310
314
|
await assembly?.load().catch(() => { });
|
|
311
|
-
const
|
|
315
|
+
const { strong, weak } = assembly
|
|
312
316
|
? searchRefNames(assembly, queryString, searchType)
|
|
313
|
-
: [];
|
|
317
|
+
: { strong: [], weak: [] };
|
|
314
318
|
return {
|
|
315
|
-
results: dedupe([
|
|
319
|
+
results: dedupe([
|
|
320
|
+
...strong,
|
|
321
|
+
...(report?.results ?? []).filter(r => landsInAssembly(r, assembly)),
|
|
322
|
+
...weak,
|
|
323
|
+
], elt => elt.getId()),
|
|
316
324
|
indexCount: report?.indexCount ?? 0,
|
|
317
325
|
failures: report?.failures ?? [],
|
|
318
326
|
};
|
|
319
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* The search box's hits for a query: refNames and text-index results, merged.
|
|
330
|
+
* Pass the session and the function finds the index manager and the assembly
|
|
331
|
+
* itself; passing `textSearchManager` and `assembly` is the older form.
|
|
332
|
+
*/
|
|
320
333
|
export async function fetchResults(args) {
|
|
321
|
-
|
|
334
|
+
if ('session' in args) {
|
|
335
|
+
const { session, ...rest } = args;
|
|
336
|
+
const assembly = await session.assemblyManager
|
|
337
|
+
.waitForAssembly(args.assemblyName)
|
|
338
|
+
.catch(() => undefined);
|
|
339
|
+
return (await searchNames({
|
|
340
|
+
...rest,
|
|
341
|
+
textSearchManager: session.textSearchManager,
|
|
342
|
+
assembly,
|
|
343
|
+
})).results;
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
return (await searchNames(args)).results;
|
|
347
|
+
}
|
|
322
348
|
}
|
|
323
349
|
// A miss says when an index could not answer: with none answering it is a
|
|
324
350
|
// failure, and with some answering it is still a miss, naming what failed
|
|
@@ -333,30 +359,24 @@ export function nameNotFound(input, assemblyName, { indexCount, failures }) {
|
|
|
333
359
|
})
|
|
334
360
|
: new SearchResultsNotFoundError(`${miss} (a search index failed: ${failure})`, { cause: failure });
|
|
335
361
|
}
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
// once enough unique canonical hits accumulate rather than lowercasing and
|
|
340
|
-
// scanning the entire list on every keystroke.
|
|
362
|
+
// The refNames a query names, through the same ranking the dropdown's fallback
|
|
363
|
+
// list uses. A refName the query is only a substring of is the weakest kind of
|
|
364
|
+
// hit, so it goes behind the text-search results rather than ahead of them
|
|
341
365
|
function searchRefNames(assembly, queryString, searchType) {
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
return [...canonicalHits].map(([r, exact]) => new RefSequenceResult({ label: r, refName: r, exact }));
|
|
366
|
+
const hits = rankRefNames(assembly, queryString, MAX_REFNAME_HITS)
|
|
367
|
+
.filter(({ tier }) => searchType !== 'exact' || tier === 'exact')
|
|
368
|
+
.map(({ refName, tier }) => ({
|
|
369
|
+
tier,
|
|
370
|
+
result: new RefSequenceResult({
|
|
371
|
+
label: refName,
|
|
372
|
+
refName,
|
|
373
|
+
exact: tier === 'exact',
|
|
374
|
+
}),
|
|
375
|
+
}));
|
|
376
|
+
return {
|
|
377
|
+
strong: hits.filter(h => h.tier !== 'substring').map(h => h.result),
|
|
378
|
+
weak: hits.filter(h => h.tier === 'substring').map(h => h.result),
|
|
379
|
+
};
|
|
360
380
|
}
|
|
361
381
|
// splits on the last instance of a character
|
|
362
382
|
export function splitLast(str, split) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-linear-genome-view",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "JBrowse 2 linear genome view",
|
|
6
6
|
"keywords": [
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
"@jbrowse/mobx-state-tree": "^6.10.0",
|
|
25
25
|
"@mui/icons-material": "^9.5.0",
|
|
26
26
|
"@mui/material": "^9.5.0",
|
|
27
|
-
"mobx": "^7.1.
|
|
28
|
-
"mobx-react": "^10.0.
|
|
29
|
-
"@jbrowse/
|
|
30
|
-
"@jbrowse/display-kit": "^5.0.0-beta.
|
|
31
|
-
"@jbrowse/launch-args": "^5.0.0-beta.
|
|
32
|
-
"@jbrowse/
|
|
33
|
-
"@jbrowse/core": "^5.0.0-beta.
|
|
27
|
+
"mobx": "^7.1.3",
|
|
28
|
+
"mobx-react": "^10.0.3",
|
|
29
|
+
"@jbrowse/core": "^5.0.0-beta.19",
|
|
30
|
+
"@jbrowse/display-kit": "^5.0.0-beta.19",
|
|
31
|
+
"@jbrowse/launch-args": "^5.0.0-beta.19",
|
|
32
|
+
"@jbrowse/display-ui": "^5.0.0-beta.19",
|
|
33
|
+
"@jbrowse/render-core": "^5.0.0-beta.19"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": ">=19.0.0",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"sideEffects": false,
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@jbrowse/display-test-utils": "^5.0.0-beta.
|
|
44
|
+
"@jbrowse/display-test-utils": "^5.0.0-beta.19"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"prebuild": "pnpm clean",
|