react-msaview 6.0.0 → 6.1.1
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 +98 -98
- package/bundle/index.js.map +4 -4
- package/dist/columnCounts.d.ts +7 -0
- package/dist/columnCounts.js +18 -0
- package/dist/columnCounts.js.map +1 -1
- package/dist/components/DragHandle.d.ts +25 -0
- package/dist/components/DragHandle.js +49 -0
- package/dist/components/DragHandle.js.map +1 -0
- package/dist/components/ResizeHandles.d.ts +4 -2
- package/dist/components/ResizeHandles.js +29 -32
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +2 -2
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/dialogs/InterProScanDialog.js +52 -129
- package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
- package/dist/components/header/settingsMenuItems.js +16 -1
- package/dist/components/header/settingsMenuItems.js.map +1 -1
- package/dist/components/minimap/Minimap.js +32 -4
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/msa/MSACanvas.js +8 -2
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +12 -3
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/msaRaster.d.ts +63 -0
- package/dist/components/msa/msaRaster.js +252 -0
- package/dist/components/msa/msaRaster.js.map +1 -0
- package/dist/components/msa/renderMSABlock.d.ts +2 -1
- package/dist/components/msa/renderMSABlock.js +13 -21
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/tileColor.d.ts +6 -0
- package/dist/components/msa/tileColor.js +35 -0
- package/dist/components/msa/tileColor.js.map +1 -0
- package/dist/components/renderCtx.d.ts +1 -1
- package/dist/components/tracks/TrackBlocks.d.ts +14 -0
- package/dist/components/tracks/TrackBlocks.js +65 -0
- package/dist/components/tracks/TrackBlocks.js.map +1 -0
- package/dist/components/tracks/{renderTracksSvg.d.ts → drawTracks.d.ts} +22 -10
- package/dist/components/tracks/drawTracks.js +193 -0
- package/dist/components/tracks/drawTracks.js.map +1 -0
- package/dist/components/tree/TreeCanvas.js +8 -2
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +7 -4
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.js +27 -21
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -1
- package/dist/model/DataModel.d.ts +1 -4
- package/dist/model/DataModel.js +8 -10
- package/dist/model/DataModel.js.map +1 -1
- package/dist/model/treeModel.d.ts +1 -1
- package/dist/model/treeModel.js +1 -1
- package/dist/model.d.ts +36 -7
- package/dist/model.js +113 -58
- package/dist/model.js.map +1 -1
- package/dist/neighborJoining.js +34 -18
- package/dist/neighborJoining.js.map +1 -1
- package/dist/renderTestEnv.d.ts +43 -0
- package/dist/renderTestEnv.js +88 -0
- package/dist/renderTestEnv.js.map +1 -0
- package/dist/renderToSvg.js +1 -1
- package/dist/renderToSvg.js.map +1 -1
- package/dist/sequenceLogo.d.ts +28 -0
- package/dist/sequenceLogo.js +47 -0
- package/dist/sequenceLogo.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/src/columnCounts.test.ts +15 -0
- package/src/columnCounts.ts +19 -0
- package/src/components/DragHandle.tsx +81 -0
- package/src/components/ResizeHandles.tsx +46 -54
- package/src/components/VerticalScrollbar.tsx +3 -2
- package/src/components/dialogs/InterProScanDialog.tsx +54 -131
- package/src/components/header/settingsMenuItems.ts +19 -1
- package/src/components/minimap/Minimap.tsx +47 -4
- package/src/components/msa/MSACanvas.tsx +30 -10
- package/src/components/msa/MSACanvasBlock.tsx +13 -3
- package/src/components/msa/msaRaster.test.ts +145 -0
- package/src/components/msa/msaRaster.ts +350 -0
- package/src/components/msa/renderMSABlock.ts +15 -20
- package/src/components/msa/tileColor.ts +37 -0
- package/src/components/renderCtx.ts +2 -0
- package/src/components/tracks/TrackBlocks.tsx +111 -0
- package/src/components/tracks/drawTracks.ts +323 -0
- package/src/components/tree/TreeCanvas.tsx +16 -4
- package/src/components/tree/TreeCanvasBlock.tsx +18 -11
- package/src/components/tree/renderTreeCanvas.test.ts +55 -0
- package/src/components/tree/renderTreeCanvas.ts +28 -19
- package/src/constants.ts +10 -0
- package/src/impgRender.test.tsx +2 -57
- package/src/largeTree.test.ts +16 -2
- package/src/model/DataModel.ts +11 -11
- package/src/model/treeModel.ts +1 -1
- package/src/model.ts +128 -60
- package/src/neighborJoining.ts +36 -18
- package/src/renderDomainsSvg.test.tsx +2 -57
- package/src/renderMinimapSvg.test.tsx +2 -56
- package/src/renderSequenceLogoSvg.test.tsx +176 -0
- package/src/renderTestEnv.ts +96 -0
- package/src/renderToSvg.tsx +1 -1
- package/src/sequenceLogo.test.ts +88 -0
- package/src/sequenceLogo.ts +63 -0
- package/src/types.ts +7 -1
- package/src/version.ts +1 -1
- package/dist/components/ConservationTrack.d.ts +0 -8
- package/dist/components/ConservationTrack.js +0 -49
- package/dist/components/ConservationTrack.js.map +0 -1
- package/dist/components/ScrollbarThumb.d.ts +0 -14
- package/dist/components/ScrollbarThumb.js +0 -28
- package/dist/components/ScrollbarThumb.js.map +0 -1
- package/dist/components/TextTrack.d.ts +0 -8
- package/dist/components/TextTrack.js +0 -58
- package/dist/components/TextTrack.js.map +0 -1
- package/dist/components/tracks/renderTracksSvg.js +0 -126
- package/dist/components/tracks/renderTracksSvg.js.map +0 -1
- package/src/components/ConservationTrack.tsx +0 -99
- package/src/components/ScrollbarThumb.tsx +0 -48
- package/src/components/TextTrack.tsx +0 -103
- package/src/components/tracks/renderTracksSvg.ts +0 -247
package/dist/model/DataModel.js
CHANGED
|
@@ -52,15 +52,13 @@ export function DataModelF() {
|
|
|
52
52
|
self.gff = gff;
|
|
53
53
|
},
|
|
54
54
|
}))
|
|
55
|
-
.postProcessSnapshot(snap =>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
};
|
|
64
|
-
});
|
|
55
|
+
.postProcessSnapshot(snap =>
|
|
56
|
+
// a large document is dropped from the snapshot rather than inlined
|
|
57
|
+
// into a session or a shared URL, and every field here holds one, so
|
|
58
|
+
// the rule is the same for all of them
|
|
59
|
+
Object.fromEntries(Object.entries(snap).map(([key, text]) => [
|
|
60
|
+
key,
|
|
61
|
+
text && text.length > 50_000 ? undefined : text,
|
|
62
|
+
])));
|
|
65
63
|
}
|
|
66
64
|
//# sourceMappingURL=DataModel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataModel.js","sourceRoot":"","sources":["../../src/model/DataModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAEhD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,KAAK;SACT,KAAK,CAAC;QACL;;WAEG;QACH,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAC/B;;WAEG;QACH,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B;;WAEG;QACH,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QACvC;;WAEG;QACH,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;KAC/B,CAAC;SACD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB;;WAEG;QACH,OAAO,CAAC,IAAa;YACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAClB,CAAC;QACD;;WAEG;QACH,MAAM,CAAC,GAAY;YACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QAChB,CAAC;QACD;;WAEG;QACH,eAAe,CAAC,YAAqB;YACnC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAClC,CAAC;QACD;;WAEG;QACH,MAAM,CAAC,GAAY;YACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QAChB,CAAC;KACF,CAAC,CAAC;SACF,mBAAmB,CAAC,IAAI,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"DataModel.js","sourceRoot":"","sources":["../../src/model/DataModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAEhD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,KAAK;SACT,KAAK,CAAC;QACL;;WAEG;QACH,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAC/B;;WAEG;QACH,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B;;WAEG;QACH,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QACvC;;WAEG;QACH,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;KAC/B,CAAC;SACD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB;;WAEG;QACH,OAAO,CAAC,IAAa;YACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAClB,CAAC;QACD;;WAEG;QACH,MAAM,CAAC,GAAY;YACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QAChB,CAAC;QACD;;WAEG;QACH,eAAe,CAAC,YAAqB;YACnC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAClC,CAAC;QACD;;WAEG;QACH,MAAM,CAAC,GAAY;YACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QAChB,CAAC;KACF,CAAC,CAAC;SACF,mBAAmB,CAAC,IAAI,CAAC,EAAE;IAC1B,oEAAoE;IACpE,qEAAqE;IACrE,uCAAuC;IACvC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;QACxC,GAAG;QACH,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;KAChD,CAAC,CACH,CACF,CAAA;AACL,CAAC"}
|
|
@@ -36,7 +36,7 @@ export declare function TreeModelF(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
36
36
|
drawTree: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
37
37
|
/**
|
|
38
38
|
* #property
|
|
39
|
-
* draw
|
|
39
|
+
* draw node bubbles on the tree; the branches stay clickable either way
|
|
40
40
|
*/
|
|
41
41
|
drawNodeBubbles: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
42
42
|
/**
|
package/dist/model/treeModel.js
CHANGED
|
@@ -41,7 +41,7 @@ export function TreeModelF() {
|
|
|
41
41
|
drawTree: stripDefault(types.boolean, defaultDrawTree),
|
|
42
42
|
/**
|
|
43
43
|
* #property
|
|
44
|
-
* draw
|
|
44
|
+
* draw node bubbles on the tree; the branches stay clickable either way
|
|
45
45
|
*/
|
|
46
46
|
drawNodeBubbles: stripDefault(types.boolean, defaultDrawNodeBubbles),
|
|
47
47
|
/**
|
package/dist/model.d.ts
CHANGED
|
@@ -518,7 +518,10 @@ declare function stateModelFactory(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
518
518
|
showOnly: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
|
|
519
519
|
/**
|
|
520
520
|
* #property
|
|
521
|
-
*
|
|
521
|
+
* the user's explicit show/hide choice per track id, keyed by id with
|
|
522
|
+
* the value meaning "off". A track the user has never touched is absent
|
|
523
|
+
* and falls back to its own default (see `defaultOffTracks`), so a
|
|
524
|
+
* hidden-by-default track adds nothing to the shared URL.
|
|
522
525
|
*/
|
|
523
526
|
turnedOffTracks: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IMapType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>, [undefined]>;
|
|
524
527
|
/**
|
|
@@ -537,10 +540,7 @@ declare function stateModelFactory(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
537
540
|
setTreeMetadata(treeMetadata?: string): void;
|
|
538
541
|
setGFF(gff?: string): void;
|
|
539
542
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, {
|
|
540
|
-
|
|
541
|
-
msa: string | undefined;
|
|
542
|
-
treeMetadata: string | undefined;
|
|
543
|
-
gff: string | undefined;
|
|
543
|
+
[k: string]: string | undefined;
|
|
544
544
|
}>, [undefined]>;
|
|
545
545
|
/**
|
|
546
546
|
* #property
|
|
@@ -664,6 +664,13 @@ declare function stateModelFactory(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
664
664
|
* #volatile
|
|
665
665
|
*/
|
|
666
666
|
conservationTrackHeight: number;
|
|
667
|
+
/**
|
|
668
|
+
* #volatile
|
|
669
|
+
* taller than the conservation track by default: the logo spends its
|
|
670
|
+
* height on stacked glyphs, and a 40px stack of four residues leaves each
|
|
671
|
+
* one too short to identify
|
|
672
|
+
*/
|
|
673
|
+
sequenceLogoTrackHeight: number;
|
|
667
674
|
/**
|
|
668
675
|
* #volatile
|
|
669
676
|
*/
|
|
@@ -1013,6 +1020,13 @@ declare function stateModelFactory(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
1013
1020
|
* Returns values 0-1 where 1 = fully conserved, 0 = no conservation.
|
|
1014
1021
|
*/
|
|
1015
1022
|
readonly conservation: number[];
|
|
1023
|
+
/**
|
|
1024
|
+
* #getter
|
|
1025
|
+
* The information content of a fully conserved column, in bits, which
|
|
1026
|
+
* depends on the alphabet. Both the entropy ceiling `conservation`
|
|
1027
|
+
* normalizes against and the y-axis ceiling of the sequence logo track.
|
|
1028
|
+
*/
|
|
1029
|
+
readonly alphabetMaxBits: number;
|
|
1016
1030
|
/**
|
|
1017
1031
|
* #getter
|
|
1018
1032
|
* Per-column conservation of physicochemical property class (amino acids
|
|
@@ -1070,6 +1084,12 @@ declare function stateModelFactory(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
1070
1084
|
* #getter
|
|
1071
1085
|
*/
|
|
1072
1086
|
readonly blocksY: number[];
|
|
1087
|
+
/**
|
|
1088
|
+
* #getter
|
|
1089
|
+
* height of the alignment viewport, px. The same subtraction as
|
|
1090
|
+
* msaAreaHeight, which is defined later in the views chain
|
|
1091
|
+
*/
|
|
1092
|
+
readonly visibleMsaHeight: number;
|
|
1073
1093
|
} & {
|
|
1074
1094
|
/**
|
|
1075
1095
|
* #getter
|
|
@@ -1086,8 +1106,7 @@ declare function stateModelFactory(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
1086
1106
|
/**
|
|
1087
1107
|
* #getter
|
|
1088
1108
|
* most-negative allowed scrollY, keeping the last row in view rather than
|
|
1089
|
-
* letting the whole alignment scroll off the top.
|
|
1090
|
-
* computed inline here because msaAreaHeight is defined later in the chain.
|
|
1109
|
+
* letting the whole alignment scroll off the top.
|
|
1091
1110
|
*/
|
|
1092
1111
|
readonly maxScrollY: number;
|
|
1093
1112
|
/**
|
|
@@ -1206,6 +1225,12 @@ declare function stateModelFactory(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
1206
1225
|
* #getter
|
|
1207
1226
|
*/
|
|
1208
1227
|
readonly labelWidthMap: Map<string, number>;
|
|
1228
|
+
/**
|
|
1229
|
+
* #getter
|
|
1230
|
+
* factor turning a labelWidthMap entry into its width at the current
|
|
1231
|
+
* font size
|
|
1232
|
+
*/
|
|
1233
|
+
readonly labelWidthScale: number;
|
|
1209
1234
|
readonly labelsWidth: number;
|
|
1210
1235
|
/**
|
|
1211
1236
|
* #getter
|
|
@@ -1446,6 +1471,10 @@ declare function stateModelFactory(): import("@jbrowse/mobx-state-tree").IModelT
|
|
|
1446
1471
|
* #action
|
|
1447
1472
|
*/
|
|
1448
1473
|
setConservationTrackHeight(arg: number): void;
|
|
1474
|
+
/**
|
|
1475
|
+
* #action
|
|
1476
|
+
*/
|
|
1477
|
+
setSequenceLogoTrackHeight(arg: number): void;
|
|
1449
1478
|
/**
|
|
1450
1479
|
* #action
|
|
1451
1480
|
*/
|
package/dist/model.js
CHANGED
|
@@ -9,9 +9,8 @@ import { calculateBlocks } from './calculateBlocks.js';
|
|
|
9
9
|
import { clustalXColumnColors } from './clustalX.js';
|
|
10
10
|
import colorSchemes from './colorSchemes.js';
|
|
11
11
|
import { columnCountsFromRows, letterOfResidueSlot } from './columnCounts.js';
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import { defaultAllowedGappyness, defaultColWidth, defaultColorSchemeName, defaultCurrentAlignment, defaultDrawMsaLetters, defaultHeight, defaultHideGaps, defaultRowHeight, defaultScrollX, defaultScrollY, defaultScrollZoom, defaultShowDomainLegend, defaultShowDomains, defaultSubFeatureRows, maxCellSize, minColWidth, minRowHeight, segmentFeatureTypes, segmentShades, } from './constants.js';
|
|
12
|
+
import TrackBlocks from './components/tracks/TrackBlocks.js';
|
|
13
|
+
import { defaultAllowedGappyness, defaultColWidth, defaultColorSchemeName, defaultCurrentAlignment, defaultDrawMsaLetters, defaultHeight, defaultHideGaps, defaultRowHeight, defaultScrollX, defaultScrollY, defaultScrollZoom, defaultShowDomainLegend, defaultShowDomains, defaultSubFeatureRows, labelReferenceFontSize, maxCellSize, minColWidth, minLetterColWidth, minLetterRowHeight, minRowHeight, segmentFeatureTypes, segmentShades, } from './constants.js';
|
|
15
14
|
import { createPaletteMap } from './createPaletteMap.js';
|
|
16
15
|
import { fetchTextWithProgress, isAbortError } from './fetchUtils.js';
|
|
17
16
|
import { flatToTree } from './flatToTree.js';
|
|
@@ -26,6 +25,7 @@ import { parseAsn1 } from './parseAsn1.js';
|
|
|
26
25
|
import { calculatePropertyConservation } from './propertyConservation.js';
|
|
27
26
|
import { globalColToVisibleCol, visibleColToGlobalCol, visibleColToSeqPosForRow, visibleColsBefore, } from './rowCoordinateCalculations.js';
|
|
28
27
|
import { buildSeqPosIndex } from './seqPosToGlobalCol.js';
|
|
28
|
+
import { maxBitsFor } from './sequenceLogo.js';
|
|
29
29
|
import { stripDefault } from './stripDefault.js';
|
|
30
30
|
import { computeRowInsertions, len, skipBlanks, transform } from './util.js';
|
|
31
31
|
import { saveAs } from './vendor/fileSaver.js';
|
|
@@ -35,6 +35,17 @@ function parseTreeText(text) {
|
|
|
35
35
|
}
|
|
36
36
|
return parseNewick(text.startsWith('SEQ') ? parseEmfTree(text).tree : text);
|
|
37
37
|
}
|
|
38
|
+
// Tracks that start hidden. The sequence logo answers a narrower question than
|
|
39
|
+
// conservation does and costs three times the vertical space, so it waits to be
|
|
40
|
+
// asked for.
|
|
41
|
+
const defaultOffTracks = new Set(['sequence-logo']);
|
|
42
|
+
// `turnedOffTracks` records the user's explicit choices only: an id is absent
|
|
43
|
+
// until they touch that track, and then its value is whether the track is OFF.
|
|
44
|
+
// Reading the default through this is what lets a track ship hidden without
|
|
45
|
+
// writing an entry into every snapshot and shared URL.
|
|
46
|
+
function trackIsOff(turnedOffTracks, id) {
|
|
47
|
+
return turnedOffTracks.get(id) ?? defaultOffTracks.has(id);
|
|
48
|
+
}
|
|
38
49
|
/**
|
|
39
50
|
* #stateModel MsaView
|
|
40
51
|
*
|
|
@@ -165,7 +176,10 @@ function stateModelFactory() {
|
|
|
165
176
|
showOnly: types.maybe(types.string),
|
|
166
177
|
/**
|
|
167
178
|
* #property
|
|
168
|
-
*
|
|
179
|
+
* the user's explicit show/hide choice per track id, keyed by id with
|
|
180
|
+
* the value meaning "off". A track the user has never touched is absent
|
|
181
|
+
* and falls back to its own default (see `defaultOffTracks`), so a
|
|
182
|
+
* hidden-by-default track adds nothing to the shared URL.
|
|
169
183
|
*/
|
|
170
184
|
turnedOffTracks: stripDefault(types.map(types.boolean), {}),
|
|
171
185
|
/**
|
|
@@ -272,6 +286,13 @@ function stateModelFactory() {
|
|
|
272
286
|
* #volatile
|
|
273
287
|
*/
|
|
274
288
|
conservationTrackHeight: 40,
|
|
289
|
+
/**
|
|
290
|
+
* #volatile
|
|
291
|
+
* taller than the conservation track by default: the logo spends its
|
|
292
|
+
* height on stacked glyphs, and a 40px stack of four residues leaves each
|
|
293
|
+
* one too short to identify
|
|
294
|
+
*/
|
|
295
|
+
sequenceLogoTrackHeight: 80,
|
|
275
296
|
/**
|
|
276
297
|
* #volatile
|
|
277
298
|
*/
|
|
@@ -877,26 +898,25 @@ function stateModelFactory() {
|
|
|
877
898
|
* Returns values 0-1 where 1 = fully conserved, 0 = no conservation.
|
|
878
899
|
*/
|
|
879
900
|
get conservation() {
|
|
880
|
-
const { colStats,
|
|
881
|
-
const alphabetSize = sequenceType === 'amino' ? 20 : 4;
|
|
882
|
-
const maxEntropy = Math.log2(alphabetSize);
|
|
901
|
+
const { colStats, alphabetMaxBits } = this;
|
|
883
902
|
return Array.from({ length: colStats.numColumns }, (_, col) => {
|
|
884
903
|
const total = colStats.total(col);
|
|
885
904
|
const gapCount = colStats.gapCount(col);
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
colStats.forEachResidue(col, (_slot, count) => {
|
|
891
|
-
const freq = count / nonGapTotal;
|
|
892
|
-
entropy -= freq * Math.log2(freq);
|
|
893
|
-
});
|
|
894
|
-
score =
|
|
895
|
-
Math.max(0, 1 - entropy / maxEntropy) * (1 - gapCount / total);
|
|
896
|
-
}
|
|
897
|
-
return score;
|
|
905
|
+
return total > gapCount
|
|
906
|
+
? Math.max(0, 1 - colStats.entropy(col) / alphabetMaxBits) *
|
|
907
|
+
(1 - gapCount / total)
|
|
908
|
+
: 0;
|
|
898
909
|
});
|
|
899
910
|
},
|
|
911
|
+
/**
|
|
912
|
+
* #getter
|
|
913
|
+
* The information content of a fully conserved column, in bits, which
|
|
914
|
+
* depends on the alphabet. Both the entropy ceiling `conservation`
|
|
915
|
+
* normalizes against and the y-axis ceiling of the sequence logo track.
|
|
916
|
+
*/
|
|
917
|
+
get alphabetMaxBits() {
|
|
918
|
+
return maxBitsFor(this.sequenceType);
|
|
919
|
+
},
|
|
900
920
|
/**
|
|
901
921
|
* #getter
|
|
902
922
|
* Per-column conservation of physicochemical property class (amino acids
|
|
@@ -1001,12 +1021,22 @@ function stateModelFactory() {
|
|
|
1001
1021
|
*/
|
|
1002
1022
|
get blocksY() {
|
|
1003
1023
|
return calculateBlocks({
|
|
1004
|
-
viewportSize:
|
|
1024
|
+
viewportSize: this.visibleMsaHeight,
|
|
1005
1025
|
viewportPos: -self.scrollY,
|
|
1006
1026
|
blockSize: self.blockSize,
|
|
1007
1027
|
mapSize: self.totalHeight,
|
|
1008
1028
|
});
|
|
1009
1029
|
},
|
|
1030
|
+
/**
|
|
1031
|
+
* #getter
|
|
1032
|
+
* height of the alignment viewport, px. The same subtraction as
|
|
1033
|
+
* msaAreaHeight, which is defined later in the views chain
|
|
1034
|
+
*/
|
|
1035
|
+
get visibleMsaHeight() {
|
|
1036
|
+
return (self.height -
|
|
1037
|
+
self.headerHeight -
|
|
1038
|
+
(self.msaAreaWidth < self.totalWidth ? self.minimapHeight : 0));
|
|
1039
|
+
},
|
|
1010
1040
|
}))
|
|
1011
1041
|
.views(self => ({
|
|
1012
1042
|
/**
|
|
@@ -1030,28 +1060,25 @@ function stateModelFactory() {
|
|
|
1030
1060
|
/**
|
|
1031
1061
|
* #getter
|
|
1032
1062
|
* most-negative allowed scrollY, keeping the last row in view rather than
|
|
1033
|
-
* letting the whole alignment scroll off the top.
|
|
1034
|
-
* computed inline here because msaAreaHeight is defined later in the chain.
|
|
1063
|
+
* letting the whole alignment scroll off the top.
|
|
1035
1064
|
*/
|
|
1036
1065
|
get maxScrollY() {
|
|
1037
|
-
|
|
1038
|
-
self.headerHeight -
|
|
1039
|
-
(self.msaAreaWidth < self.totalWidth ? self.minimapHeight : 0);
|
|
1040
|
-
return Math.min(-self.totalHeight + visibleHeight, 0);
|
|
1066
|
+
return Math.min(-self.totalHeight + self.visibleMsaHeight, 0);
|
|
1041
1067
|
},
|
|
1042
1068
|
/**
|
|
1043
1069
|
* #getter
|
|
1044
1070
|
*/
|
|
1045
1071
|
get showMsaLetters() {
|
|
1046
1072
|
return (self.drawMsaLetters &&
|
|
1047
|
-
self.rowHeight >=
|
|
1073
|
+
self.rowHeight >= minLetterRowHeight &&
|
|
1074
|
+
self.colWidth >= minLetterColWidth &&
|
|
1048
1075
|
self.colWidth > self.rowHeight / 2);
|
|
1049
1076
|
},
|
|
1050
1077
|
/**
|
|
1051
1078
|
* #getter
|
|
1052
1079
|
*/
|
|
1053
1080
|
get showTreeText() {
|
|
1054
|
-
return self.drawLabels && self.rowHeight >=
|
|
1081
|
+
return self.drawLabels && self.rowHeight >= minLetterRowHeight;
|
|
1055
1082
|
},
|
|
1056
1083
|
}))
|
|
1057
1084
|
.actions(self => ({
|
|
@@ -1232,12 +1259,9 @@ function stateModelFactory() {
|
|
|
1232
1259
|
* #action
|
|
1233
1260
|
*/
|
|
1234
1261
|
toggleTrack(id) {
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
else {
|
|
1239
|
-
self.turnedOffTracks.set(id, true);
|
|
1240
|
-
}
|
|
1262
|
+
// the stored value is "is off", so the current shown state is exactly
|
|
1263
|
+
// what the flipped entry should hold
|
|
1264
|
+
self.turnedOffTracks.set(id, !trackIsOff(self.turnedOffTracks, id));
|
|
1241
1265
|
},
|
|
1242
1266
|
/**
|
|
1243
1267
|
* #action
|
|
@@ -1251,10 +1275,13 @@ function stateModelFactory() {
|
|
|
1251
1275
|
* #getter
|
|
1252
1276
|
*/
|
|
1253
1277
|
get labelWidthMap() {
|
|
1254
|
-
const { showTreeText, leaves, treeMetadata
|
|
1278
|
+
const { showTreeText, leaves, treeMetadata } = self;
|
|
1255
1279
|
// gated on the same condition the renderer draws labels under, so the
|
|
1256
1280
|
// gutter labelsWidth reserves and the labels actually drawn cannot
|
|
1257
|
-
// disagree -- and so turning labels off hands their space to the tree
|
|
1281
|
+
// disagree -- and so turning labels off hands their space to the tree.
|
|
1282
|
+
// Measured at a fixed reference size and scaled by labelWidthScale:
|
|
1283
|
+
// re-measuring every leaf on every vertical-zoom frame cost ~200ms on a
|
|
1284
|
+
// 50k-leaf tree
|
|
1258
1285
|
return showTreeText
|
|
1259
1286
|
? new Map(leaves.map(node => {
|
|
1260
1287
|
const { name } = node.data;
|
|
@@ -1262,10 +1289,21 @@ function stateModelFactory() {
|
|
|
1262
1289
|
// to the row name, and measuring '' would size the gutter (and
|
|
1263
1290
|
// the label's click target) to nothing
|
|
1264
1291
|
const displayName = treeMetadata[name]?.genome || name;
|
|
1265
|
-
return [
|
|
1292
|
+
return [
|
|
1293
|
+
name,
|
|
1294
|
+
measureTextCanvas(displayName, labelReferenceFontSize),
|
|
1295
|
+
];
|
|
1266
1296
|
}))
|
|
1267
1297
|
: new Map();
|
|
1268
1298
|
},
|
|
1299
|
+
/**
|
|
1300
|
+
* #getter
|
|
1301
|
+
* factor turning a labelWidthMap entry into its width at the current
|
|
1302
|
+
* font size
|
|
1303
|
+
*/
|
|
1304
|
+
get labelWidthScale() {
|
|
1305
|
+
return self.fontSize / labelReferenceFontSize;
|
|
1306
|
+
},
|
|
1269
1307
|
get labelsWidth() {
|
|
1270
1308
|
// a loop, not Math.max(...widths.values()): spreading a map of every
|
|
1271
1309
|
// leaf passes one argument per row, and the argument limit is somewhere
|
|
@@ -1278,7 +1316,7 @@ function stateModelFactory() {
|
|
|
1278
1316
|
max = width;
|
|
1279
1317
|
}
|
|
1280
1318
|
}
|
|
1281
|
-
return max;
|
|
1319
|
+
return max * this.labelWidthScale;
|
|
1282
1320
|
},
|
|
1283
1321
|
/**
|
|
1284
1322
|
* #getter
|
|
@@ -1303,10 +1341,11 @@ function stateModelFactory() {
|
|
|
1303
1341
|
.map(t => ({
|
|
1304
1342
|
model: {
|
|
1305
1343
|
...t,
|
|
1344
|
+
kind: 'text',
|
|
1306
1345
|
data: hideGapsEffective ? skipBlanks(blanks, t.data) : t.data,
|
|
1307
1346
|
height: rowHeight,
|
|
1308
1347
|
},
|
|
1309
|
-
ReactComponent:
|
|
1348
|
+
ReactComponent: TrackBlocks,
|
|
1310
1349
|
}));
|
|
1311
1350
|
},
|
|
1312
1351
|
/**
|
|
@@ -1314,34 +1353,41 @@ function stateModelFactory() {
|
|
|
1314
1353
|
*/
|
|
1315
1354
|
get tracks() {
|
|
1316
1355
|
const conservationTrack = {
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
},
|
|
1323
|
-
ReactComponent: ConservationTrack,
|
|
1356
|
+
id: 'conservation',
|
|
1357
|
+
name: 'Conservation',
|
|
1358
|
+
kind: 'bar',
|
|
1359
|
+
height: self.conservationTrackHeight,
|
|
1360
|
+
barColor: 'gray',
|
|
1324
1361
|
};
|
|
1325
1362
|
const propertyConservationTrack = {
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1363
|
+
id: 'property-conservation',
|
|
1364
|
+
name: 'Property conservation',
|
|
1365
|
+
kind: 'bar',
|
|
1366
|
+
height: self.conservationTrackHeight,
|
|
1367
|
+
barColor: '#6a51a3',
|
|
1368
|
+
};
|
|
1369
|
+
const sequenceLogoTrack = {
|
|
1370
|
+
id: 'sequence-logo',
|
|
1371
|
+
name: 'Sequence logo',
|
|
1372
|
+
kind: 'logo',
|
|
1373
|
+
height: self.sequenceLogoTrackHeight,
|
|
1333
1374
|
};
|
|
1334
1375
|
return [
|
|
1335
1376
|
...this.adapterTrackModels,
|
|
1336
|
-
|
|
1337
|
-
|
|
1377
|
+
...[
|
|
1378
|
+
conservationTrack,
|
|
1379
|
+
...(self.sequenceType === 'amino'
|
|
1380
|
+
? [propertyConservationTrack]
|
|
1381
|
+
: []),
|
|
1382
|
+
sequenceLogoTrack,
|
|
1383
|
+
].map(model => ({ model, ReactComponent: TrackBlocks })),
|
|
1338
1384
|
];
|
|
1339
1385
|
},
|
|
1340
1386
|
/**
|
|
1341
1387
|
* #getter
|
|
1342
1388
|
*/
|
|
1343
1389
|
get turnedOnTracks() {
|
|
1344
|
-
return this.tracks.filter(f => !self.turnedOffTracks
|
|
1390
|
+
return this.tracks.filter(f => !trackIsOff(self.turnedOffTracks, f.model.id));
|
|
1345
1391
|
},
|
|
1346
1392
|
/**
|
|
1347
1393
|
* #getter
|
|
@@ -1575,9 +1621,9 @@ function stateModelFactory() {
|
|
|
1575
1621
|
* needs to keep residues readable on top of the boxes.
|
|
1576
1622
|
*/
|
|
1577
1623
|
get domainBands() {
|
|
1624
|
+
const { blanks } = self;
|
|
1578
1625
|
const bands = new Map();
|
|
1579
1626
|
for (const [name, annotations] of Object.entries(self.annotationsByRow)) {
|
|
1580
|
-
const { blanks } = self;
|
|
1581
1627
|
const rowBands = annotations
|
|
1582
1628
|
.toSorted((a, b) => len(b) - len(a))
|
|
1583
1629
|
.map(annotation => {
|
|
@@ -1687,8 +1733,11 @@ function stateModelFactory() {
|
|
|
1687
1733
|
return undefined;
|
|
1688
1734
|
}
|
|
1689
1735
|
const { colStats } = self;
|
|
1736
|
+
if (mouseCol >= colStats.numColumns) {
|
|
1737
|
+
return undefined;
|
|
1738
|
+
}
|
|
1690
1739
|
const total = colStats.total(mouseCol);
|
|
1691
|
-
if (
|
|
1740
|
+
if (!total) {
|
|
1692
1741
|
return undefined;
|
|
1693
1742
|
}
|
|
1694
1743
|
const gaps = colStats.gapCount(mouseCol);
|
|
@@ -1732,6 +1781,12 @@ function stateModelFactory() {
|
|
|
1732
1781
|
setConservationTrackHeight(arg) {
|
|
1733
1782
|
self.conservationTrackHeight = arg;
|
|
1734
1783
|
},
|
|
1784
|
+
/**
|
|
1785
|
+
* #action
|
|
1786
|
+
*/
|
|
1787
|
+
setSequenceLogoTrackHeight(arg) {
|
|
1788
|
+
self.sequenceLogoTrackHeight = arg;
|
|
1789
|
+
},
|
|
1735
1790
|
/**
|
|
1736
1791
|
* #action
|
|
1737
1792
|
*/
|