react-msaview 9.1.1 → 9.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/bundle/index.js +79 -79
- package/bundle/index.js.map +4 -4
- package/dist/components/DragHandle.js +2 -1
- package/dist/components/DragHandle.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +31 -19
- package/dist/components/MSAViewer.js +2 -1
- package/dist/components/MSAViewer.js.map +1 -1
- package/dist/components/Track.js +2 -5
- package/dist/components/Track.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +1 -1
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/header/Header.js +2 -1
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/minimap/Minimap.js +1 -1
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/msa/MSACanvas.js +16 -27
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/rowpanels/RowPanels.js +8 -6
- package/dist/components/rowpanels/RowPanels.js.map +1 -1
- package/dist/components/settings/SettingsPanel.js +2 -1
- package/dist/components/settings/SettingsPanel.js.map +1 -1
- package/dist/components/settings/TrackList.js +8 -5
- package/dist/components/settings/TrackList.js.map +1 -1
- package/dist/components/tracks/TrackTooltipContent.js +2 -1
- package/dist/components/tracks/TrackTooltipContent.js.map +1 -1
- package/dist/components/tracks/drawTracks.js +13 -6
- package/dist/components/tracks/drawTracks.js.map +1 -1
- package/dist/components/tree/TreeCanvas.js +8 -6
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/element.d.ts +11 -7
- package/dist/element.js +46 -8
- package/dist/element.js.map +1 -1
- package/dist/featurePanels.d.ts +0 -7
- package/dist/featurePanels.js +1 -16
- package/dist/featurePanels.js.map +1 -1
- package/dist/ggplotPalettes.js +12 -1
- package/dist/ggplotPalettes.js.map +1 -1
- package/dist/groupKeys.d.ts +6 -0
- package/dist/groupKeys.js +52 -0
- package/dist/groupKeys.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/model.d.ts +40 -17
- package/dist/model.js +123 -54
- package/dist/model.js.map +1 -1
- package/dist/scales.d.ts +114 -13
- package/dist/scales.js +154 -19
- package/dist/scales.js.map +1 -1
- package/dist/svgTestUtil.d.ts +22 -12
- package/dist/types.d.ts +30 -28
- package/dist/useDragScroll.d.ts +4 -3
- package/dist/useDragScroll.js +9 -6
- package/dist/useDragScroll.js.map +1 -1
- package/dist/useWheelScroll.d.ts +26 -8
- package/dist/useWheelScroll.js +108 -71
- package/dist/useWheelScroll.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/viewerSnapshot.js +2 -1
- package/dist/viewerSnapshot.js.map +1 -1
- package/package.json +3 -3
- package/src/components/DragHandle.tsx +2 -1
- package/src/components/MSAViewer.tsx +11 -8
- package/src/components/Track.tsx +2 -8
- package/src/components/VerticalScrollbar.tsx +1 -1
- package/src/components/header/Header.tsx +2 -1
- package/src/components/minimap/Minimap.tsx +1 -1
- package/src/components/msa/MSACanvas.tsx +14 -35
- package/src/components/rowpanels/RowPanels.tsx +8 -10
- package/src/components/settings/SettingsPanel.tsx +2 -1
- package/src/components/settings/TrackList.tsx +9 -4
- package/src/components/tracks/TrackTooltipContent.tsx +2 -1
- package/src/components/tracks/drawTracks.ts +15 -7
- package/src/components/tree/TreeCanvas.tsx +8 -10
- package/src/constants.ts +2 -0
- package/src/element.ts +53 -8
- package/src/featurePanels.ts +1 -25
- package/src/ggplotPalettes.ts +13 -1
- package/src/groupKeys.ts +54 -0
- package/src/index.ts +13 -2
- package/src/model.ts +174 -72
- package/src/scales.ts +268 -25
- package/src/types.ts +29 -26
- package/src/useDragScroll.ts +11 -8
- package/src/useWheelScroll.ts +124 -84
- package/src/version.ts +1 -1
- package/src/viewerSnapshot.ts +3 -1
package/dist/model.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ColumnStats } from './columnStats.ts';
|
|
|
2
2
|
import type { ScrollZoomAxis } from './constants.ts';
|
|
3
3
|
import type { HierarchyNode } from './hierarchy.ts';
|
|
4
4
|
import type { ExportSvgOptions } from './renderToSvg.tsx';
|
|
5
|
+
import type { ColorChannel, LegacyColumnTrack, LegacyEncoding, LegacyRowPanel, ScaleTable, SharedScale } from './scales.ts';
|
|
5
6
|
import type { Annotation, Arc, BasicTrack, Cell, Clade, ResidueMappingProblem, ColumnTrackSpec, DomainBand, Encoding, Feature, Highlight, Legend, MsaSelection, NodeWithIds, Region, ResidueMapping, ResolvedClade, ResolvedEncoding, ResolvedFeaturePanel, ResolvedStripPanel, ResolvedHighlight, ResolvedSelection, TreeRoot, ResolvedRowPanel, RowDataInput, RowPanelSpec, RowResidue, StructureResidue, TrackKind, UnshareableData, Viewport } from './types.ts';
|
|
6
7
|
import type { ZoomSnapshot } from './zoomSnapshot.ts';
|
|
7
8
|
import type { FileLocation as FileLocationType } from '@jbrowse/core/util/types';
|
|
@@ -542,7 +543,7 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
542
543
|
* tracks supplied as data: per-column values drawn as bars, or a
|
|
543
544
|
* per-column string drawn as a text track. See docs/layers.md
|
|
544
545
|
*/
|
|
545
|
-
columnTracks: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<ColumnTrackSpec, ColumnTrackSpec, ColumnTrackSpec>>, [undefined]>;
|
|
546
|
+
columnTracks: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").ISnapshotProcessor<import("@jbrowse/mobx-state-tree").IType<ColumnTrackSpec, ColumnTrackSpec, ColumnTrackSpec>, ColumnTrackSpec, import("@jbrowse/mobx-state-tree")._NotCustomized>>, [undefined]>;
|
|
546
547
|
/**
|
|
547
548
|
* #property
|
|
548
549
|
* row-to-structure residue correspondence, computed outside the viewer
|
|
@@ -634,20 +635,21 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
634
635
|
clades: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<Clade, Clade, Clade>>, [undefined]>;
|
|
635
636
|
/**
|
|
636
637
|
* #property
|
|
637
|
-
* what the viewer's own marks read from `rowData
|
|
638
|
-
* `{channel, field,
|
|
639
|
-
* `
|
|
638
|
+
* what the viewer's own marks read from `rowData` or the feature
|
|
639
|
+
* table: `{channel, field, range?, domain?, title?}` per channel. The
|
|
640
|
+
* earlier `scale: {palette}` and `scale: {map}` read as `range` and
|
|
641
|
+
* `domain`. See docs/layers.md
|
|
640
642
|
*/
|
|
641
|
-
encodings: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<Encoding, Encoding, Encoding>>, [undefined]>;
|
|
643
|
+
encodings: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").ISnapshotProcessor<import("@jbrowse/mobx-state-tree").IType<Encoding, Encoding, Encoding>, Encoding | LegacyEncoding, import("@jbrowse/mobx-state-tree")._NotCustomized>>, [undefined]>;
|
|
642
644
|
/**
|
|
643
645
|
* #property
|
|
644
646
|
* panels drawn between the tree and the alignment:
|
|
645
|
-
* `{kind: "strip", field,
|
|
646
|
-
* per row from a `rowData` field, and
|
|
647
|
+
* `{kind: "strip", field, range?, domain?, title?, width?, header?}`
|
|
648
|
+
* colors one cell per row from a `rowData` field, and
|
|
647
649
|
* `{kind: "features", x, encoding?, transform?, width?, header?}`
|
|
648
650
|
* draws the spans the GFF carries. See docs/layers.md
|
|
649
651
|
*/
|
|
650
|
-
rowPanels: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<RowPanelSpec, RowPanelSpec, RowPanelSpec>>, [undefined]>;
|
|
652
|
+
rowPanels: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").ISnapshotProcessor<import("@jbrowse/mobx-state-tree").IType<RowPanelSpec, RowPanelSpec, RowPanelSpec>, LegacyRowPanel | RowPanelSpec, import("@jbrowse/mobx-state-tree")._NotCustomized>>, [undefined]>;
|
|
651
653
|
}, {
|
|
652
654
|
queueOfDialogs: [import("@jbrowse/core/util").DialogComponentType, any][];
|
|
653
655
|
} & {
|
|
@@ -739,7 +741,8 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
739
741
|
volatileWidth: number | undefined;
|
|
740
742
|
/**
|
|
741
743
|
* #volatile
|
|
742
|
-
*
|
|
744
|
+
* thickness of the dividers, between the tree and the alignment and under
|
|
745
|
+
* the view, px
|
|
743
746
|
*/
|
|
744
747
|
resizeHandleWidth: number;
|
|
745
748
|
/**
|
|
@@ -1594,6 +1597,12 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
1594
1597
|
* and the alphabet, not on zoom
|
|
1595
1598
|
*/
|
|
1596
1599
|
readonly computedTrackModels: BasicTrack[];
|
|
1600
|
+
/**
|
|
1601
|
+
* #getter
|
|
1602
|
+
* the reference row (`relativeTo`) repeated above the alignment, so it
|
|
1603
|
+
* stays in view while the rows compared against it scroll
|
|
1604
|
+
*/
|
|
1605
|
+
readonly referenceTrackModels: BasicTrack[];
|
|
1597
1606
|
readonly tracks: BasicTrack[];
|
|
1598
1607
|
/**
|
|
1599
1608
|
* #getter
|
|
@@ -1992,7 +2001,7 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
1992
2001
|
/**
|
|
1993
2002
|
* #action
|
|
1994
2003
|
*/
|
|
1995
|
-
setColumnTracks(tracks: ColumnTrackSpec[]): void;
|
|
2004
|
+
setColumnTracks(tracks: (ColumnTrackSpec | LegacyColumnTrack)[]): void;
|
|
1996
2005
|
/**
|
|
1997
2006
|
* #action
|
|
1998
2007
|
* replace the row table, which the model keeps as the JSON string
|
|
@@ -2003,12 +2012,12 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
2003
2012
|
* #action
|
|
2004
2013
|
* replace what the viewer's marks read from the row table
|
|
2005
2014
|
*/
|
|
2006
|
-
setEncodings(encodings: Encoding[]): void;
|
|
2015
|
+
setEncodings(encodings: (Encoding | LegacyEncoding)[]): void;
|
|
2007
2016
|
/**
|
|
2008
2017
|
* #action
|
|
2009
2018
|
* replace the panels drawn between the tree and the alignment
|
|
2010
2019
|
*/
|
|
2011
|
-
setRowPanels(panels: RowPanelSpec[]): void;
|
|
2020
|
+
setRowPanels(panels: (RowPanelSpec | LegacyRowPanel)[]): void;
|
|
2012
2021
|
/**
|
|
2013
2022
|
* #action
|
|
2014
2023
|
* replace the alignment<->structure correspondence (see docs/layers.md)
|
|
@@ -2115,11 +2124,10 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
2115
2124
|
* the categorical color keys drawn for this view, shared by the on-screen
|
|
2116
2125
|
* legend overlay and the SVG export's reserved column. The domain overlay
|
|
2117
2126
|
* produces the first, listing the `featureFill` scale where an encoding
|
|
2118
|
-
* names one. Every
|
|
2119
|
-
* produces one more, so two channels
|
|
2120
|
-
*
|
|
2121
|
-
*
|
|
2122
|
-
* legend between them
|
|
2127
|
+
* names one. Every scale a row-table encoding or a row panel reads
|
|
2128
|
+
* produces one more, keyed by its declaration, so two channels or two
|
|
2129
|
+
* strips declaring one scale list it once, and strips over eight fields
|
|
2130
|
+
* naming one `title` list one legend between them
|
|
2123
2131
|
*/
|
|
2124
2132
|
readonly legends: Legend[];
|
|
2125
2133
|
/**
|
|
@@ -2250,6 +2258,21 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
2250
2258
|
* table or the encodings, never per row per frame.
|
|
2251
2259
|
*/
|
|
2252
2260
|
readonly resolvedEncodings: ResolvedEncoding[];
|
|
2261
|
+
/**
|
|
2262
|
+
* #getter
|
|
2263
|
+
* every color object the encodings and the row panels declare, keyed
|
|
2264
|
+
* by declaration (`declarationKey`) and resolved once over the union
|
|
2265
|
+
* of the values its records' fields take, so a value two strips share
|
|
2266
|
+
* takes one color in both. A feature field reads every feature loaded,
|
|
2267
|
+
* so hiding a type in the filter dialog leaves the rest in their
|
|
2268
|
+
* colors, and its legend lists the values of the drawn features.
|
|
2269
|
+
*/
|
|
2270
|
+
readonly resolvedScales: Map<string, SharedScale>;
|
|
2271
|
+
/**
|
|
2272
|
+
* #method
|
|
2273
|
+
* the shared scale a record's color object resolves to
|
|
2274
|
+
*/
|
|
2275
|
+
scaleOf(channel: ColorChannel, table: ScaleTable): SharedScale;
|
|
2253
2276
|
/**
|
|
2254
2277
|
* #getter
|
|
2255
2278
|
* each row panel's scale resolved against the values its field takes,
|
package/dist/model.js
CHANGED
|
@@ -13,11 +13,11 @@ import { packDomainLanes } from './components/msa/packDomainLanes.js';
|
|
|
13
13
|
import { visibleColRange } from './components/msa/visibleColRange.js';
|
|
14
14
|
import { cladeGutterWidth } from './components/tree/cladeBrackets.js';
|
|
15
15
|
import { scaleBarLength } from './components/tree/scaleBar.js';
|
|
16
|
-
import { defaultAllowedGappyness, defaultColWidth, defaultColorSchemeName, defaultCurrentAlignment, defaultDrawMsaLetters, defaultHeight, defaultHideGaps, defaultRowHeight, defaultScrollX, defaultScrollY, defaultScrollZoom, defaultScrollZoomAxis, defaultShowDomainLegend, defaultShowDomains, defaultSubFeatureRows, fontSizeFor, labelFitFontSize, maxCellSize, maxFitTreeWidth, maxTreeAreaShare, maxInlineSnapshotBytes as defaultMaxInlineSnapshotBytes, maxNeighborJoiningRows, minColWidth, minLetterColWidth, minLetterRowHeight, minRowHeight, minTreeWidth, pxPerTreeDepth, rowPanelHeaderHeight, rowTintAlpha, scrollZoomAxes, segmentFeatureTypes, segmentShades, settingsPanelWidth, treeScaleBarHeight, } from './constants.js';
|
|
16
|
+
import { defaultAllowedGappyness, defaultColWidth, defaultColorSchemeName, defaultCurrentAlignment, defaultDrawMsaLetters, defaultHeight, defaultHideGaps, defaultRowHeight, defaultScrollX, defaultScrollY, defaultScrollZoom, defaultScrollZoomAxis, defaultShowDomainLegend, defaultShowDomains, defaultSubFeatureRows, fontSizeFor, labelFitFontSize, maxCellSize, maxFitTreeWidth, maxTreeAreaShare, maxInlineSnapshotBytes as defaultMaxInlineSnapshotBytes, maxNeighborJoiningRows, minColWidth, minLetterColWidth, minLetterRowHeight, minRowHeight, minTreeWidth, pxPerTreeDepth, resizeHandleWidth, rowPanelHeaderHeight, rowTintAlpha, scrollZoomAxes, segmentFeatureTypes, segmentShades, settingsPanelWidth, treeScaleBarHeight, } from './constants.js';
|
|
17
17
|
import { createPaletteMap } from './createPaletteMap.js';
|
|
18
18
|
import { exportFileName } from './exportFileName.js';
|
|
19
|
-
import { featureName } from './featureFields.js';
|
|
20
|
-
import { colorByRow, featureColorMap, featureLabelMap, featurePanelSpans,
|
|
19
|
+
import { featureField, featureName } from './featureFields.js';
|
|
20
|
+
import { colorByRow, featureColorMap, featureLabelMap, featurePanelSpans, rowPanelWidth, stringFields, } from './featurePanels.js';
|
|
21
21
|
import { featuresToAnnotations } from './featuresLayer.js';
|
|
22
22
|
import { installFilehandleLoader } from './filehandleLoader.js';
|
|
23
23
|
import { find, hierarchy, layoutTree, leaves, nodeCoveringRows, } from './hierarchy.js';
|
|
@@ -29,7 +29,7 @@ import { calculateNeighborJoiningTree } from './neighborJoining.js';
|
|
|
29
29
|
import { calculatePropertyConservation } from './propertyConservation.js';
|
|
30
30
|
import { preorder } from './rerootTree.js';
|
|
31
31
|
import { globalColToVisibleCol, seqPosOfGlobalCol, visibleColToGlobalCol, visibleColsBefore, } from './rowCoordinateCalculations.js';
|
|
32
|
-
import {
|
|
32
|
+
import { colorTable, declarationKey, readColumnTrack, readEncoding, readRowPanel, resolveShared, } from './scales.js';
|
|
33
33
|
import { buildSeqPosIndex } from './seqPosToGlobalCol.js';
|
|
34
34
|
import { maxBitsFor } from './sequenceLogo.js';
|
|
35
35
|
import { blosum62ColumnColors, identityColumnColors, } from './similarityColors.js';
|
|
@@ -391,7 +391,9 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
391
391
|
* tracks supplied as data: per-column values drawn as bars, or a
|
|
392
392
|
* per-column string drawn as a text track. See docs/layers.md
|
|
393
393
|
*/
|
|
394
|
-
columnTracks: stripDefault(types.array(types.frozen()
|
|
394
|
+
columnTracks: stripDefault(types.array(types.snapshotProcessor(types.frozen(), {
|
|
395
|
+
preProcessor: readColumnTrack,
|
|
396
|
+
})), []),
|
|
395
397
|
/**
|
|
396
398
|
* #property
|
|
397
399
|
* row-to-structure residue correspondence, computed outside the viewer
|
|
@@ -471,20 +473,25 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
471
473
|
clades: stripDefault(types.array(types.frozen()), []),
|
|
472
474
|
/**
|
|
473
475
|
* #property
|
|
474
|
-
* what the viewer's own marks read from `rowData
|
|
475
|
-
* `{channel, field,
|
|
476
|
-
* `
|
|
476
|
+
* what the viewer's own marks read from `rowData` or the feature
|
|
477
|
+
* table: `{channel, field, range?, domain?, title?}` per channel. The
|
|
478
|
+
* earlier `scale: {palette}` and `scale: {map}` read as `range` and
|
|
479
|
+
* `domain`. See docs/layers.md
|
|
477
480
|
*/
|
|
478
|
-
encodings: stripDefault(types.array(types.frozen()
|
|
481
|
+
encodings: stripDefault(types.array(types.snapshotProcessor(types.frozen(), {
|
|
482
|
+
preProcessor: readEncoding,
|
|
483
|
+
})), []),
|
|
479
484
|
/**
|
|
480
485
|
* #property
|
|
481
486
|
* panels drawn between the tree and the alignment:
|
|
482
|
-
* `{kind: "strip", field,
|
|
483
|
-
* per row from a `rowData` field, and
|
|
487
|
+
* `{kind: "strip", field, range?, domain?, title?, width?, header?}`
|
|
488
|
+
* colors one cell per row from a `rowData` field, and
|
|
484
489
|
* `{kind: "features", x, encoding?, transform?, width?, header?}`
|
|
485
490
|
* draws the spans the GFF carries. See docs/layers.md
|
|
486
491
|
*/
|
|
487
|
-
rowPanels: stripDefault(types.array(types.frozen()
|
|
492
|
+
rowPanels: stripDefault(types.array(types.snapshotProcessor(types.frozen(), {
|
|
493
|
+
preProcessor: readRowPanel,
|
|
494
|
+
})), []),
|
|
488
495
|
}))
|
|
489
496
|
.volatile(() => ({
|
|
490
497
|
/**
|
|
@@ -545,9 +552,10 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
545
552
|
volatileWidth: undefined,
|
|
546
553
|
/**
|
|
547
554
|
* #volatile
|
|
548
|
-
*
|
|
555
|
+
* thickness of the dividers, between the tree and the alignment and under
|
|
556
|
+
* the view, px
|
|
549
557
|
*/
|
|
550
|
-
resizeHandleWidth
|
|
558
|
+
resizeHandleWidth,
|
|
551
559
|
/**
|
|
552
560
|
* #volatile
|
|
553
561
|
* size of blocks of content to be drawn, px
|
|
@@ -1943,7 +1951,7 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1943
1951
|
return [track.id, { arcs }];
|
|
1944
1952
|
}
|
|
1945
1953
|
if (track.kind === 'bar') {
|
|
1946
|
-
const max = track.
|
|
1954
|
+
const max = track.scales?.y?.domainMax ?? 1;
|
|
1947
1955
|
const values = skip(project(track, track.values ?? [], 0)).map(v => Math.min(1, Math.max(0, v / max)));
|
|
1948
1956
|
return [track.id, { values }];
|
|
1949
1957
|
}
|
|
@@ -1987,7 +1995,12 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1987
1995
|
height: this.trackHeight(track.kind, heightKey, track.height),
|
|
1988
1996
|
barColor: track.color,
|
|
1989
1997
|
arcColor: track.color,
|
|
1990
|
-
customColorScheme: track.
|
|
1998
|
+
customColorScheme: track.encoding?.color
|
|
1999
|
+
? colorTable(track.encoding.color, [
|
|
2000
|
+
...(track.encoding.color.domain ?? []),
|
|
2001
|
+
...new Set(track.data),
|
|
2002
|
+
])
|
|
2003
|
+
: undefined,
|
|
1991
2004
|
data: content?.data,
|
|
1992
2005
|
arcs: content?.arcs,
|
|
1993
2006
|
},
|
|
@@ -2117,6 +2130,28 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2117
2130
|
},
|
|
2118
2131
|
}));
|
|
2119
2132
|
},
|
|
2133
|
+
/**
|
|
2134
|
+
* #getter
|
|
2135
|
+
* the reference row (`relativeTo`) repeated above the alignment, so it
|
|
2136
|
+
* stays in view while the rows compared against it scroll
|
|
2137
|
+
*/
|
|
2138
|
+
get referenceTrackModels() {
|
|
2139
|
+
const { relativeTo } = self;
|
|
2140
|
+
const data = relativeTo === undefined ? undefined : self.columns.get(relativeTo);
|
|
2141
|
+
return relativeTo === undefined || data === undefined
|
|
2142
|
+
? []
|
|
2143
|
+
: [
|
|
2144
|
+
{
|
|
2145
|
+
model: {
|
|
2146
|
+
id: 'reference-row',
|
|
2147
|
+
name: relativeTo,
|
|
2148
|
+
kind: 'reference',
|
|
2149
|
+
data,
|
|
2150
|
+
height: self.rowHeight,
|
|
2151
|
+
},
|
|
2152
|
+
},
|
|
2153
|
+
];
|
|
2154
|
+
},
|
|
2120
2155
|
get tracks() {
|
|
2121
2156
|
return [
|
|
2122
2157
|
...this.adapterTrackModels,
|
|
@@ -2125,6 +2160,7 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2125
2160
|
// every computed track reads the alignment's columns, and a tree, a
|
|
2126
2161
|
// GFF and a features panel draw a figure with none
|
|
2127
2162
|
...(self.numColumns > 0 ? this.computedTrackModels : []),
|
|
2163
|
+
...this.referenceTrackModels,
|
|
2128
2164
|
];
|
|
2129
2165
|
},
|
|
2130
2166
|
/**
|
|
@@ -2888,7 +2924,7 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2888
2924
|
* #action
|
|
2889
2925
|
*/
|
|
2890
2926
|
setColumnTracks(tracks) {
|
|
2891
|
-
self.columnTracks.replace(tracks);
|
|
2927
|
+
self.columnTracks.replace(tracks.map(readColumnTrack));
|
|
2892
2928
|
},
|
|
2893
2929
|
/**
|
|
2894
2930
|
* #action
|
|
@@ -2903,14 +2939,14 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2903
2939
|
* replace what the viewer's marks read from the row table
|
|
2904
2940
|
*/
|
|
2905
2941
|
setEncodings(encodings) {
|
|
2906
|
-
self.encodings.replace(encodings);
|
|
2942
|
+
self.encodings.replace(encodings.map(readEncoding));
|
|
2907
2943
|
},
|
|
2908
2944
|
/**
|
|
2909
2945
|
* #action
|
|
2910
2946
|
* replace the panels drawn between the tree and the alignment
|
|
2911
2947
|
*/
|
|
2912
2948
|
setRowPanels(panels) {
|
|
2913
|
-
self.rowPanels.replace(panels);
|
|
2949
|
+
self.rowPanels.replace(panels.map(readRowPanel));
|
|
2914
2950
|
},
|
|
2915
2951
|
/**
|
|
2916
2952
|
* #action
|
|
@@ -3093,52 +3129,47 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
3093
3129
|
* the categorical color keys drawn for this view, shared by the on-screen
|
|
3094
3130
|
* legend overlay and the SVG export's reserved column. The domain overlay
|
|
3095
3131
|
* produces the first, listing the `featureFill` scale where an encoding
|
|
3096
|
-
* names one. Every
|
|
3097
|
-
* produces one more, so two channels
|
|
3098
|
-
*
|
|
3099
|
-
*
|
|
3100
|
-
* legend between them
|
|
3132
|
+
* names one. Every scale a row-table encoding or a row panel reads
|
|
3133
|
+
* produces one more, keyed by its declaration, so two channels or two
|
|
3134
|
+
* strips declaring one scale list it once, and strips over eight fields
|
|
3135
|
+
* naming one `title` list one legend between them
|
|
3101
3136
|
*/
|
|
3102
3137
|
get legends() {
|
|
3103
3138
|
const { featureFillEncoding, fillPalette, visibleDomainTypes } = this;
|
|
3104
3139
|
const byKey = new Map();
|
|
3140
|
+
const ids = new Set();
|
|
3105
3141
|
// the accession palette keys on no field, so it takes a key of its own
|
|
3106
|
-
const add = (
|
|
3107
|
-
|
|
3142
|
+
const add = (key, title, entries, overlay = false) => {
|
|
3143
|
+
const k = key ?? 'domains';
|
|
3144
|
+
if (entries.length === 0 || byKey.has(k)) {
|
|
3108
3145
|
return;
|
|
3109
3146
|
}
|
|
3110
|
-
const
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
legend.entries.push(...entries.filter(e => !seen.has(e.id)));
|
|
3115
|
-
}
|
|
3116
|
-
else {
|
|
3117
|
-
byKey.set(key, {
|
|
3118
|
-
id: id ?? (field === undefined ? 'domains' : `rowData-${field}`),
|
|
3119
|
-
title: field ?? 'Domains',
|
|
3120
|
-
entries: [...entries],
|
|
3121
|
-
});
|
|
3147
|
+
const base = overlay || key === undefined ? 'domains' : `rowData-${title}`;
|
|
3148
|
+
let id = base;
|
|
3149
|
+
for (let n = 2; ids.has(id); n++) {
|
|
3150
|
+
id = `${base}-${n}`;
|
|
3122
3151
|
}
|
|
3152
|
+
ids.add(id);
|
|
3153
|
+
byKey.set(k, { id, title: title ?? 'Domains', entries });
|
|
3123
3154
|
};
|
|
3124
3155
|
// the overlay draws the domain key; with no columns it draws nothing,
|
|
3125
3156
|
// and a features panel taking the same colors lists them instead
|
|
3126
3157
|
if (self.actuallyShowDomains && self.numColumns > 0) {
|
|
3127
|
-
add(featureFillEncoding?.
|
|
3158
|
+
add(featureFillEncoding?.key, featureFillEncoding?.title, featureFillEncoding
|
|
3128
3159
|
? featureFillEncoding.legend
|
|
3129
3160
|
: visibleDomainTypes.map(d => ({
|
|
3130
3161
|
id: d.accession,
|
|
3131
3162
|
label: d.name,
|
|
3132
3163
|
color: d.color ?? fillPalette[d.accession],
|
|
3133
|
-
})),
|
|
3164
|
+
})), true);
|
|
3134
3165
|
}
|
|
3135
|
-
for (const { channel,
|
|
3166
|
+
for (const { channel, key, title, legend } of this.resolvedEncodings) {
|
|
3136
3167
|
if (!featureChannels.has(channel)) {
|
|
3137
|
-
add(
|
|
3168
|
+
add(key, title, legend);
|
|
3138
3169
|
}
|
|
3139
3170
|
}
|
|
3140
|
-
for (const { legendTitle, legend } of this.rowPanelScales) {
|
|
3141
|
-
add(legendTitle, legend);
|
|
3171
|
+
for (const { legendKey, legendTitle, legend } of this.rowPanelScales) {
|
|
3172
|
+
add(legendKey, legendTitle, legend);
|
|
3142
3173
|
}
|
|
3143
3174
|
return [...byKey.values()];
|
|
3144
3175
|
},
|
|
@@ -3412,14 +3443,52 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
3412
3443
|
* table or the encodings, never per row per frame.
|
|
3413
3444
|
*/
|
|
3414
3445
|
get resolvedEncodings() {
|
|
3415
|
-
const rows = Object.values(self.rowData);
|
|
3416
3446
|
return self.encodings.map(encoding => ({
|
|
3417
3447
|
...encoding,
|
|
3418
|
-
...(featureChannels.has(encoding.channel)
|
|
3419
|
-
? resolveFeatureScale(encoding.field, encoding.scale, self.allAnnotations, self.filteredAnnotations)
|
|
3420
|
-
: resolveScale(encoding.scale, rows.map(row => row?.[encoding.field]).filter(notEmpty))),
|
|
3448
|
+
...this.scaleOf(encoding, featureChannels.has(encoding.channel) ? 'features' : 'rows'),
|
|
3421
3449
|
}));
|
|
3422
3450
|
},
|
|
3451
|
+
/**
|
|
3452
|
+
* #getter
|
|
3453
|
+
* every color object the encodings and the row panels declare, keyed
|
|
3454
|
+
* by declaration (`declarationKey`) and resolved once over the union
|
|
3455
|
+
* of the values its records' fields take, so a value two strips share
|
|
3456
|
+
* takes one color in both. A feature field reads every feature loaded,
|
|
3457
|
+
* so hiding a type in the filter dialog leaves the rest in their
|
|
3458
|
+
* colors, and its legend lists the values of the drawn features.
|
|
3459
|
+
*/
|
|
3460
|
+
get resolvedScales() {
|
|
3461
|
+
const rows = Object.values(self.rowData);
|
|
3462
|
+
const featureValues = (list, field) => list.map(a => featureField(a, field)).filter(notEmpty);
|
|
3463
|
+
const use = (channel, table) => ({
|
|
3464
|
+
spec: channel,
|
|
3465
|
+
field: channel.field,
|
|
3466
|
+
table,
|
|
3467
|
+
...(table === 'rows'
|
|
3468
|
+
? {
|
|
3469
|
+
values: rows.map(row => row?.[channel.field]).filter(notEmpty),
|
|
3470
|
+
}
|
|
3471
|
+
: {
|
|
3472
|
+
values: featureValues(self.allAnnotations, channel.field),
|
|
3473
|
+
shown: featureValues(self.filteredAnnotations, channel.field),
|
|
3474
|
+
}),
|
|
3475
|
+
});
|
|
3476
|
+
return resolveShared([
|
|
3477
|
+
...self.encodings.map(encoding => use(encoding, featureChannels.has(encoding.channel) ? 'features' : 'rows')),
|
|
3478
|
+
...self.rowPanels.flatMap(panel => panel.kind === 'strip'
|
|
3479
|
+
? [use(panel, 'rows')]
|
|
3480
|
+
: panel.encoding?.color
|
|
3481
|
+
? [use(panel.encoding.color, 'features')]
|
|
3482
|
+
: []),
|
|
3483
|
+
]);
|
|
3484
|
+
},
|
|
3485
|
+
/**
|
|
3486
|
+
* #method
|
|
3487
|
+
* the shared scale a record's color object resolves to
|
|
3488
|
+
*/
|
|
3489
|
+
scaleOf(channel, table) {
|
|
3490
|
+
return this.resolvedScales.get(declarationKey({ spec: channel, field: channel.field, table }));
|
|
3491
|
+
},
|
|
3423
3492
|
/**
|
|
3424
3493
|
* #getter
|
|
3425
3494
|
* each row panel's scale resolved against the values its field takes,
|
|
@@ -3434,7 +3503,7 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
3434
3503
|
if (panel.kind === 'features') {
|
|
3435
3504
|
const color = panel.encoding?.color;
|
|
3436
3505
|
const encoding = color
|
|
3437
|
-
?
|
|
3506
|
+
? { field: color.field, ...this.scaleOf(color, 'features') }
|
|
3438
3507
|
: featureFillEncoding;
|
|
3439
3508
|
const label = panel.encoding?.label;
|
|
3440
3509
|
return {
|
|
@@ -3442,7 +3511,8 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
3442
3511
|
x: panel.x,
|
|
3443
3512
|
header: panel.header ?? '',
|
|
3444
3513
|
field: encoding?.field,
|
|
3445
|
-
|
|
3514
|
+
legendKey: encoding?.key,
|
|
3515
|
+
legendTitle: encoding?.title,
|
|
3446
3516
|
colors: color
|
|
3447
3517
|
? featureColorMap(annotations, encoding, fillPalette)
|
|
3448
3518
|
: this.featureColors,
|
|
@@ -3457,14 +3527,13 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
3457
3527
|
})),
|
|
3458
3528
|
};
|
|
3459
3529
|
}
|
|
3460
|
-
const { colorOf, legend } =
|
|
3461
|
-
.map(row => row?.[panel.field])
|
|
3462
|
-
.filter(notEmpty));
|
|
3530
|
+
const { colorOf, legend, key, title } = this.scaleOf(panel, 'rows');
|
|
3463
3531
|
return {
|
|
3464
3532
|
kind: panel.kind,
|
|
3465
3533
|
field: panel.field,
|
|
3466
3534
|
header: panel.header ?? panel.field,
|
|
3467
|
-
|
|
3535
|
+
legendKey: key,
|
|
3536
|
+
legendTitle: title,
|
|
3468
3537
|
colors: colorByRow(rowData, panel.field, colorOf),
|
|
3469
3538
|
legend,
|
|
3470
3539
|
};
|