react-msaview 4.4.0 → 4.4.2
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 +15 -15
- package/bundle/index.js.LICENSE.txt +5 -13
- package/bundle/index.js.map +1 -1
- package/dist/colorSchemes.js +2 -2
- package/dist/colorSchemes.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +2 -2
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/dialogs/SettingsDialog.js +3 -2
- package/dist/components/dialogs/SettingsDialog.js.map +1 -1
- package/dist/components/header/Header.js +1 -1
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/HeaderInfoArea.js +3 -2
- package/dist/components/header/HeaderInfoArea.js.map +1 -1
- package/dist/components/header/HeaderMenu.js +15 -97
- package/dist/components/header/HeaderMenu.js.map +1 -1
- package/dist/components/header/SettingsMenu.js +57 -73
- package/dist/components/header/SettingsMenu.js.map +1 -1
- package/dist/components/header/ZoomMenu.js +14 -2
- package/dist/components/header/ZoomMenu.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js +4 -1
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +4 -4
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSABlock.js +13 -9
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/model.d.ts +17 -5
- package/dist/model.js +70 -57
- package/dist/model.js.map +1 -1
- package/dist/rowCoordinateCalculations.d.ts +13 -2
- package/dist/rowCoordinateCalculations.js +60 -17
- package/dist/rowCoordinateCalculations.js.map +1 -1
- package/dist/rowCoordinateCalculations.test.js +96 -2
- package/dist/rowCoordinateCalculations.test.js.map +1 -1
- package/dist/seqCoordToRowSpecificGlobalCoord.d.ts +4 -0
- package/dist/seqCoordToRowSpecificGlobalCoord.js +15 -0
- package/dist/seqCoordToRowSpecificGlobalCoord.js.map +1 -0
- package/dist/seqCoordToRowSpecificGlobalCoord.test.d.ts +1 -0
- package/dist/seqCoordToRowSpecificGlobalCoord.test.js +42 -0
- package/dist/seqCoordToRowSpecificGlobalCoord.test.js.map +1 -0
- package/dist/util.d.ts +1 -6
- package/dist/util.js +5 -22
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/colorSchemes.ts +2 -2
- package/src/components/VerticalScrollbar.tsx +2 -3
- package/src/components/dialogs/SettingsDialog.tsx +4 -2
- package/src/components/header/Header.tsx +1 -1
- package/src/components/header/HeaderInfoArea.tsx +5 -2
- package/src/components/header/HeaderMenu.tsx +15 -110
- package/src/components/header/SettingsMenu.tsx +64 -81
- package/src/components/header/ZoomMenu.tsx +15 -2
- package/src/components/msa/MSAMouseoverCanvas.tsx +4 -1
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +4 -4
- package/src/components/msa/renderMSABlock.ts +26 -22
- package/src/model.ts +89 -67
- package/src/rowCoordinateCalculations.test.ts +138 -2
- package/src/rowCoordinateCalculations.ts +95 -18
- package/src/seqCoordToRowSpecificGlobalCoord.test.ts +53 -0
- package/src/seqCoordToRowSpecificGlobalCoord.ts +20 -0
- package/src/util.ts +5 -28
- package/src/version.ts +1 -1
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import React, { lazy } from 'react'
|
|
2
2
|
|
|
3
3
|
import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'
|
|
4
|
-
import AccountTreeIcon from '@mui/icons-material/AccountTree'
|
|
5
4
|
import Assignment from '@mui/icons-material/Assignment'
|
|
6
5
|
import FilterAlt from '@mui/icons-material/FilterAlt'
|
|
7
6
|
import FolderOpen from '@mui/icons-material/FolderOpen'
|
|
8
|
-
import GridOn from '@mui/icons-material/GridOn'
|
|
9
7
|
import List from '@mui/icons-material/List'
|
|
10
8
|
import MoreVert from '@mui/icons-material/Menu'
|
|
11
9
|
import PhotoCamera from '@mui/icons-material/PhotoCamera'
|
|
12
10
|
import Search from '@mui/icons-material/Search'
|
|
13
|
-
import Settings from '@mui/icons-material/Settings'
|
|
14
11
|
import Sort from '@mui/icons-material/Sort'
|
|
15
12
|
import Visibility from '@mui/icons-material/Visibility'
|
|
16
13
|
import { observer } from 'mobx-react'
|
|
@@ -18,30 +15,18 @@ import { observer } from 'mobx-react'
|
|
|
18
15
|
import type { MsaViewModel } from '../../model'
|
|
19
16
|
|
|
20
17
|
// lazies
|
|
21
|
-
const SettingsDialog = lazy(() => import('../dialogs/SettingsDialog'))
|
|
22
18
|
const MetadataDialog = lazy(() => import('../dialogs/MetadataDialog'))
|
|
23
19
|
const TracklistDialog = lazy(() => import('../dialogs/TracklistDialog'))
|
|
24
20
|
const ExportSVGDialog = lazy(() => import('../dialogs/ExportSVGDialog'))
|
|
25
21
|
const FeatureFilterDialog = lazy(() => import('../dialogs/FeatureDialog'))
|
|
22
|
+
const SettingsDialog = lazy(() => import('../dialogs/SettingsDialog'))
|
|
26
23
|
const UserProvidedDomainsDialog = lazy(
|
|
27
24
|
() => import('../dialogs/UserProvidedDomainsDialog'),
|
|
28
25
|
)
|
|
29
26
|
const InterProScanDialog = lazy(() => import('../dialogs/InterProScanDialog'))
|
|
30
27
|
|
|
31
28
|
const HeaderMenu = observer(({ model }: { model: MsaViewModel }) => {
|
|
32
|
-
const {
|
|
33
|
-
drawTree,
|
|
34
|
-
showBranchLen,
|
|
35
|
-
labelsAlignRight,
|
|
36
|
-
drawNodeBubbles,
|
|
37
|
-
showDomains,
|
|
38
|
-
actuallyShowDomains,
|
|
39
|
-
subFeatureRows,
|
|
40
|
-
drawLabels,
|
|
41
|
-
treeWidthMatchesArea,
|
|
42
|
-
noDomains,
|
|
43
|
-
noTree,
|
|
44
|
-
} = model
|
|
29
|
+
const { showDomains, actuallyShowDomains, subFeatureRows, noDomains } = model
|
|
45
30
|
return (
|
|
46
31
|
<CascadingMenuButton
|
|
47
32
|
menuItems={[
|
|
@@ -52,98 +37,6 @@ const HeaderMenu = observer(({ model }: { model: MsaViewModel }) => {
|
|
|
52
37
|
model.reset()
|
|
53
38
|
},
|
|
54
39
|
},
|
|
55
|
-
{
|
|
56
|
-
icon: Settings,
|
|
57
|
-
label: 'Settings',
|
|
58
|
-
type: 'subMenu',
|
|
59
|
-
subMenu: [
|
|
60
|
-
{
|
|
61
|
-
label: 'Tree settings',
|
|
62
|
-
type: 'subMenu',
|
|
63
|
-
icon: AccountTreeIcon,
|
|
64
|
-
subMenu: [
|
|
65
|
-
{
|
|
66
|
-
label: 'Show branch length',
|
|
67
|
-
type: 'checkbox',
|
|
68
|
-
checked: showBranchLen,
|
|
69
|
-
onClick: () => {
|
|
70
|
-
model.setShowBranchLen(!showBranchLen)
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
label: 'Show tree',
|
|
75
|
-
type: 'checkbox',
|
|
76
|
-
checked: drawTree,
|
|
77
|
-
onClick: () => {
|
|
78
|
-
model.setDrawTree(!drawTree)
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
label: 'Draw clickable bubbles on tree branches',
|
|
83
|
-
type: 'checkbox',
|
|
84
|
-
checked: drawNodeBubbles,
|
|
85
|
-
onClick: () => {
|
|
86
|
-
model.setDrawNodeBubbles(!drawNodeBubbles)
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
label: 'Tree labels align right',
|
|
91
|
-
type: 'checkbox',
|
|
92
|
-
checked: labelsAlignRight,
|
|
93
|
-
onClick: () => {
|
|
94
|
-
model.setLabelsAlignRight(!labelsAlignRight)
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
label: 'Draw labels',
|
|
99
|
-
type: 'checkbox',
|
|
100
|
-
checked: drawLabels,
|
|
101
|
-
onClick: () => {
|
|
102
|
-
model.setDrawLabels(!drawLabels)
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
...(noTree
|
|
106
|
-
? []
|
|
107
|
-
: [
|
|
108
|
-
{
|
|
109
|
-
label: 'Make tree width fit to tree area',
|
|
110
|
-
type: 'checkbox' as const,
|
|
111
|
-
checked: treeWidthMatchesArea,
|
|
112
|
-
onClick: () => {
|
|
113
|
-
model.setTreeWidthMatchesArea(!treeWidthMatchesArea)
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
]),
|
|
117
|
-
],
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
label: 'MSA settings',
|
|
121
|
-
type: 'subMenu',
|
|
122
|
-
icon: GridOn,
|
|
123
|
-
subMenu: [],
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
label: 'More',
|
|
127
|
-
icon: Settings,
|
|
128
|
-
type: 'subMenu',
|
|
129
|
-
subMenu: [
|
|
130
|
-
{
|
|
131
|
-
label: 'More settings',
|
|
132
|
-
onClick: () => {
|
|
133
|
-
model.queueDialog(onClose => [
|
|
134
|
-
SettingsDialog,
|
|
135
|
-
{
|
|
136
|
-
model,
|
|
137
|
-
onClose,
|
|
138
|
-
},
|
|
139
|
-
])
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
},
|
|
144
|
-
],
|
|
145
|
-
},
|
|
146
|
-
|
|
147
40
|
{
|
|
148
41
|
label: 'Metadata',
|
|
149
42
|
icon: Assignment,
|
|
@@ -158,7 +51,19 @@ const HeaderMenu = observer(({ model }: { model: MsaViewModel }) => {
|
|
|
158
51
|
},
|
|
159
52
|
},
|
|
160
53
|
{
|
|
161
|
-
label: '
|
|
54
|
+
label: 'More settings',
|
|
55
|
+
onClick: () => {
|
|
56
|
+
model.queueDialog(onClose => [
|
|
57
|
+
SettingsDialog,
|
|
58
|
+
{
|
|
59
|
+
model,
|
|
60
|
+
onClose,
|
|
61
|
+
},
|
|
62
|
+
])
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
label: 'Extra tracks',
|
|
162
67
|
icon: List,
|
|
163
68
|
onClick: () => {
|
|
164
69
|
model.queueDialog(onClose => [
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react'
|
|
2
2
|
|
|
3
3
|
import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import GridOn from '@mui/icons-material/GridOn'
|
|
4
|
+
import Palette from '@mui/icons-material/Palette'
|
|
5
|
+
import AccountTree from '@mui/icons-material/AccountTree'
|
|
7
6
|
import Settings from '@mui/icons-material/Settings'
|
|
8
7
|
import { observer } from 'mobx-react'
|
|
9
8
|
|
|
@@ -11,32 +10,83 @@ import colorSchemes from '../../colorSchemes'
|
|
|
11
10
|
|
|
12
11
|
import type { MsaViewModel } from '../../model'
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
const SettingsDialog = lazy(() => import('../dialogs/SettingsDialog'))
|
|
16
|
-
|
|
17
|
-
const SettingsMenu = observer(({ model }: { model: MsaViewModel }) => {
|
|
13
|
+
const SettingsMenu = observer(function ({ model }: { model: MsaViewModel }) {
|
|
18
14
|
const {
|
|
15
|
+
colorSchemeName,
|
|
16
|
+
drawMsaLetters,
|
|
17
|
+
contrastLettering,
|
|
18
|
+
hideGaps,
|
|
19
|
+
bgColor,
|
|
19
20
|
drawTree,
|
|
20
21
|
showBranchLen,
|
|
21
22
|
labelsAlignRight,
|
|
22
23
|
drawNodeBubbles,
|
|
23
24
|
drawLabels,
|
|
24
25
|
treeWidthMatchesArea,
|
|
25
|
-
drawMsaLetters,
|
|
26
26
|
noTree,
|
|
27
|
-
bgColor,
|
|
28
|
-
hideGaps,
|
|
29
|
-
contrastLettering,
|
|
30
|
-
colorSchemeName,
|
|
31
27
|
} = model
|
|
32
28
|
return (
|
|
33
29
|
<CascadingMenuButton
|
|
34
30
|
closeAfterItemClick={false}
|
|
35
31
|
menuItems={[
|
|
32
|
+
{
|
|
33
|
+
label: 'Color scheme',
|
|
34
|
+
icon: Palette,
|
|
35
|
+
type: 'subMenu',
|
|
36
|
+
subMenu: Object.keys(colorSchemes).map(
|
|
37
|
+
option =>
|
|
38
|
+
({
|
|
39
|
+
label: option,
|
|
40
|
+
type: 'radio',
|
|
41
|
+
checked: colorSchemeName === option,
|
|
42
|
+
onClick: () => {
|
|
43
|
+
model.setColorSchemeName(option)
|
|
44
|
+
},
|
|
45
|
+
}) as const,
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: 'MSA settings',
|
|
50
|
+
type: 'subMenu',
|
|
51
|
+
subMenu: [
|
|
52
|
+
{
|
|
53
|
+
label: 'Draw letters',
|
|
54
|
+
type: 'checkbox',
|
|
55
|
+
checked: drawMsaLetters,
|
|
56
|
+
onClick: () => {
|
|
57
|
+
model.setDrawMsaLetters(!drawMsaLetters)
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: 'Color letters instead of background of tiles',
|
|
62
|
+
type: 'checkbox',
|
|
63
|
+
checked: !bgColor,
|
|
64
|
+
onClick: () => {
|
|
65
|
+
model.setBgColor(!bgColor)
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
label: 'Use contrast lettering',
|
|
70
|
+
type: 'checkbox',
|
|
71
|
+
checked: contrastLettering,
|
|
72
|
+
onClick: () => {
|
|
73
|
+
model.setContrastLettering(!contrastLettering)
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: 'Enable hiding gappy columns?',
|
|
78
|
+
type: 'checkbox',
|
|
79
|
+
checked: hideGaps,
|
|
80
|
+
onClick: () => {
|
|
81
|
+
model.setHideGaps(!hideGaps)
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
36
86
|
{
|
|
37
87
|
label: 'Tree settings',
|
|
38
88
|
type: 'subMenu',
|
|
39
|
-
icon:
|
|
89
|
+
icon: AccountTree,
|
|
40
90
|
subMenu: [
|
|
41
91
|
{
|
|
42
92
|
label: 'Show branch length',
|
|
@@ -92,73 +142,6 @@ const SettingsMenu = observer(({ model }: { model: MsaViewModel }) => {
|
|
|
92
142
|
]),
|
|
93
143
|
],
|
|
94
144
|
},
|
|
95
|
-
{
|
|
96
|
-
label: 'MSA settings',
|
|
97
|
-
type: 'subMenu',
|
|
98
|
-
icon: GridOn,
|
|
99
|
-
subMenu: [
|
|
100
|
-
{
|
|
101
|
-
label: 'Draw letters',
|
|
102
|
-
type: 'checkbox',
|
|
103
|
-
checked: drawMsaLetters,
|
|
104
|
-
onClick: () => {
|
|
105
|
-
model.setDrawMsaLetters(!drawMsaLetters)
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
label: 'Color letters instead of background of tiles',
|
|
110
|
-
type: 'checkbox',
|
|
111
|
-
checked: !bgColor,
|
|
112
|
-
onClick: () => {
|
|
113
|
-
model.setBgColor(!bgColor)
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
label: 'Use contrast lettering',
|
|
118
|
-
type: 'checkbox',
|
|
119
|
-
checked: contrastLettering,
|
|
120
|
-
onClick: () => {
|
|
121
|
-
model.setContrastLettering(!contrastLettering)
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
label: 'Enable hiding gappy columns?',
|
|
126
|
-
type: 'checkbox',
|
|
127
|
-
checked: hideGaps,
|
|
128
|
-
onClick: () => {
|
|
129
|
-
model.setHideGaps(!hideGaps)
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
],
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
label: 'Color scheme',
|
|
136
|
-
type: 'subMenu',
|
|
137
|
-
icon: ColorLensIcon,
|
|
138
|
-
subMenu: Object.keys(colorSchemes).map(
|
|
139
|
-
option =>
|
|
140
|
-
({
|
|
141
|
-
label: option,
|
|
142
|
-
type: 'radio',
|
|
143
|
-
checked: colorSchemeName === option,
|
|
144
|
-
onClick: () => {
|
|
145
|
-
model.setColorSchemeName(option)
|
|
146
|
-
},
|
|
147
|
-
}) as const,
|
|
148
|
-
),
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
label: 'More settings',
|
|
152
|
-
onClick: () => {
|
|
153
|
-
model.queueDialog(onClose => [
|
|
154
|
-
SettingsDialog,
|
|
155
|
-
{
|
|
156
|
-
model,
|
|
157
|
-
onClose,
|
|
158
|
-
},
|
|
159
|
-
])
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
145
|
]}
|
|
163
146
|
>
|
|
164
147
|
<Settings />
|
|
@@ -12,11 +12,24 @@ const ZoomMenu = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
12
12
|
<CascadingMenuButton
|
|
13
13
|
menuItems={[
|
|
14
14
|
{
|
|
15
|
-
label: 'Fit
|
|
15
|
+
label: 'Fit both vertically/horizontally',
|
|
16
16
|
onClick: () => {
|
|
17
|
-
model.
|
|
17
|
+
model.fit()
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
label: 'Fit vertically',
|
|
22
|
+
onClick: () => {
|
|
23
|
+
model.fitVertically()
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
label: 'Fit horizontally',
|
|
28
|
+
onClick: () => {
|
|
29
|
+
model.fitHorizontally()
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
|
|
20
33
|
{
|
|
21
34
|
label: 'Reset zoom to default',
|
|
22
35
|
icon: RestartAlt,
|
|
@@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { autorun } from 'mobx'
|
|
4
4
|
import { observer } from 'mobx-react'
|
|
5
|
+
import { isAlive } from 'mobx-state-tree'
|
|
5
6
|
|
|
6
7
|
import { renderMouseover } from './renderMSAMouseover'
|
|
7
8
|
|
|
@@ -18,7 +19,9 @@ const MSAMouseoverCanvas = observer(function ({
|
|
|
18
19
|
const ctx = ref.current?.getContext('2d')
|
|
19
20
|
return ctx
|
|
20
21
|
? autorun(() => {
|
|
21
|
-
|
|
22
|
+
if (isAlive(model)) {
|
|
23
|
+
renderMouseover({ ctx, model })
|
|
24
|
+
}
|
|
22
25
|
})
|
|
23
26
|
: undefined
|
|
24
27
|
}, [model])
|
|
@@ -56,7 +56,8 @@ function drawTiles({
|
|
|
56
56
|
tidyFilteredGatheredInterProAnnotations,
|
|
57
57
|
} = model
|
|
58
58
|
|
|
59
|
-
for (
|
|
59
|
+
for (let i = 0, l1 = visibleLeaves.length; i < l1; i++) {
|
|
60
|
+
const node = visibleLeaves[i]!
|
|
60
61
|
const {
|
|
61
62
|
x,
|
|
62
63
|
data: { name },
|
|
@@ -65,9 +66,9 @@ function drawTiles({
|
|
|
65
66
|
|
|
66
67
|
const entry = tidyFilteredGatheredInterProAnnotations[name]
|
|
67
68
|
|
|
68
|
-
let j = 0
|
|
69
69
|
if (entry) {
|
|
70
|
-
for (
|
|
70
|
+
for (let j = 0, l2 = entry.length; j < l2; j++) {
|
|
71
|
+
const { start, end, accession } = entry[j]!
|
|
71
72
|
const m1 = model.seqCoordToRowSpecificGlobalCoord(name, start - 1)
|
|
72
73
|
const m2 = model.seqCoordToRowSpecificGlobalCoord(name, end)
|
|
73
74
|
const x = m1 * colWidth
|
|
@@ -78,7 +79,6 @@ function drawTiles({
|
|
|
78
79
|
const lw = colWidth * (m2 - m1)
|
|
79
80
|
ctx.fillRect(x, t, lw, h)
|
|
80
81
|
ctx.strokeRect(x, t, lw, h)
|
|
81
|
-
j++
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -34,6 +34,7 @@ export function renderMSABlock({
|
|
|
34
34
|
highResScaleFactor,
|
|
35
35
|
actuallyShowDomains,
|
|
36
36
|
leaves,
|
|
37
|
+
bgColor,
|
|
37
38
|
} = model
|
|
38
39
|
const k = highResScaleFactorOverride || highResScaleFactor
|
|
39
40
|
const bx = blockSizeXOverride || blockSize
|
|
@@ -42,7 +43,7 @@ export function renderMSABlock({
|
|
|
42
43
|
ctx.scale(k, k)
|
|
43
44
|
ctx.translate(-offsetX, rowHeight / 2 - offsetY)
|
|
44
45
|
ctx.textAlign = 'center'
|
|
45
|
-
ctx.font = ctx.font.replace(/\d+px/, `${fontSize}px`)
|
|
46
|
+
ctx.font = ctx.font.replace(/\d+px/, `${bgColor ? '' : 'bold '}${fontSize}px`)
|
|
46
47
|
|
|
47
48
|
const yStart = Math.max(0, Math.floor((offsetY - rowHeight) / rowHeight))
|
|
48
49
|
const yEnd = Math.max(0, Math.ceil((offsetY + by + rowHeight) / rowHeight))
|
|
@@ -102,38 +103,40 @@ function drawTiles({
|
|
|
102
103
|
rowHeight,
|
|
103
104
|
} = model
|
|
104
105
|
|
|
105
|
-
for (
|
|
106
|
+
for (let i = 0, l1 = visibleLeaves.length; i < l1; i++) {
|
|
107
|
+
const node = visibleLeaves[i]!
|
|
106
108
|
const {
|
|
107
109
|
data: { name },
|
|
108
110
|
} = node
|
|
109
111
|
const y = node.x!
|
|
110
112
|
const str = columns[name]?.slice(xStart, xEnd)
|
|
111
113
|
if (str) {
|
|
112
|
-
for (let i = 0
|
|
114
|
+
for (let i = 0, l2 = str.length; i < l2; i++) {
|
|
113
115
|
const letter = str[i]!
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
const r1 = colorSchemeName === 'clustalx_protein_dynamic'
|
|
117
|
+
const r2 = colorSchemeName === 'percent_identity_dynamic'
|
|
118
|
+
const color = r1
|
|
119
|
+
? getClustalXColor(
|
|
120
|
+
// use model.colStats dot notation here: delay use of colStats
|
|
121
|
+
// until absolutely needed
|
|
122
|
+
model.colStats[xStart + i]!,
|
|
123
|
+
model.colStatsSums[xStart + i]!,
|
|
124
|
+
model,
|
|
125
|
+
name,
|
|
126
|
+
xStart + i,
|
|
127
|
+
)
|
|
128
|
+
: r2
|
|
129
|
+
? getPercentIdentityColor(
|
|
130
|
+
// use model.colStats dot notation here: delay use of
|
|
131
|
+
// colStats until absolutely needed
|
|
119
132
|
model.colStats[xStart + i]!,
|
|
120
133
|
model.colStatsSums[xStart + i]!,
|
|
121
134
|
model,
|
|
122
135
|
name,
|
|
123
136
|
xStart + i,
|
|
124
137
|
)
|
|
125
|
-
:
|
|
126
|
-
|
|
127
|
-
// use model.colStats dot notation here: delay use of
|
|
128
|
-
// colStats until absolutely needed
|
|
129
|
-
model.colStats[xStart + i]!,
|
|
130
|
-
model.colStatsSums[xStart + i]!,
|
|
131
|
-
model,
|
|
132
|
-
name,
|
|
133
|
-
xStart + i,
|
|
134
|
-
)
|
|
135
|
-
: colorScheme[letter.toUpperCase()]
|
|
136
|
-
if (bgColor) {
|
|
138
|
+
: colorScheme[letter.toUpperCase()]
|
|
139
|
+
if (bgColor || r1 || r2) {
|
|
137
140
|
ctx.fillStyle = color || theme.palette.background.default
|
|
138
141
|
ctx.fillRect(
|
|
139
142
|
i * colWidth + offsetX - (offsetX % colWidth),
|
|
@@ -176,14 +179,15 @@ function drawText({
|
|
|
176
179
|
rowHeight,
|
|
177
180
|
} = model
|
|
178
181
|
if (showMsaLetters) {
|
|
179
|
-
for (
|
|
182
|
+
for (let i = 0, l1 = visibleLeaves.length; i < l1; i++) {
|
|
183
|
+
const node = visibleLeaves[i]!
|
|
180
184
|
const {
|
|
181
185
|
data: { name },
|
|
182
186
|
} = node
|
|
183
187
|
const y = node.x!
|
|
184
188
|
const str = columns[name]?.slice(xStart, xEnd)
|
|
185
189
|
if (str) {
|
|
186
|
-
for (let i = 0
|
|
190
|
+
for (let i = 0, l2 = str.length; i < l2; i++) {
|
|
187
191
|
const letter = str[i]!
|
|
188
192
|
const color = colorScheme[letter.toUpperCase()]
|
|
189
193
|
const contrast = contrastLettering
|