react-msaview 5.4.0 → 5.5.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/LICENSE +21 -0
- package/bundle/index.js +465 -138
- package/bundle/index.js.map +7 -1
- package/dist/colorSchemes.js +11 -7
- package/dist/colorSchemes.js.map +1 -1
- package/dist/components/Checkbox2.js +3 -1
- package/dist/components/Checkbox2.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +7 -1
- package/dist/components/MSAViewer.js +11 -10
- package/dist/components/MSAViewer.js.map +1 -1
- package/dist/components/Track.js +8 -5
- package/dist/components/Track.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +27 -23
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/InterProScanDialog.js +2 -1
- package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
- package/dist/components/header/MultiAlignmentSelector.js +0 -0
- package/dist/components/header/MultiAlignmentSelector.js.map +1 -1
- package/dist/components/msa/DomainLegend.d.ts +6 -0
- package/dist/components/msa/DomainLegend.js +41 -0
- package/dist/components/msa/DomainLegend.js.map +1 -0
- package/dist/components/msa/MSACanvasBlock.js +17 -5
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAPanel.js +3 -1
- package/dist/components/msa/MSAPanel.js.map +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +58 -14
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSABlock.js +7 -9
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +32 -4
- package/dist/components/msa/renderMSAMouseover.js.map +1 -1
- package/dist/components/renderCtx.d.ts +1 -1
- package/dist/components/tracks/renderTracksSvg.js +4 -4
- package/dist/components/tracks/renderTracksSvg.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.js +3 -0
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +16 -0
- package/dist/constants.js.map +1 -1
- package/dist/createPaletteMap.d.ts +5 -2
- package/dist/createPaletteMap.js +15 -5
- package/dist/createPaletteMap.js.map +1 -1
- package/dist/hierarchy.js +4 -1
- package/dist/hierarchy.js.map +1 -1
- package/dist/launchInterProScan.d.ts +2 -0
- package/dist/launchInterProScan.js.map +1 -1
- package/dist/model/msaModel.js.map +1 -1
- package/dist/model.d.ts +100 -3
- package/dist/model.js +121 -19
- package/dist/model.js.map +1 -1
- package/dist/neighborJoining.js +44 -30
- package/dist/neighborJoining.js.map +1 -1
- package/dist/renderToSvg.js +104 -74
- package/dist/renderToSvg.js.map +1 -1
- package/dist/{webpack.js → umd.js} +1 -1
- package/dist/umd.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -7
- package/src/colorSchemes.ts +12 -7
- package/src/components/Checkbox2.tsx +7 -1
- package/src/components/MSAViewer.tsx +31 -21
- package/src/components/Track.tsx +8 -5
- package/src/components/dialogs/FeatureDialog.tsx +62 -48
- package/src/components/dialogs/InterProScanDialog.tsx +2 -1
- package/src/components/header/MultiAlignmentSelector.tsx +0 -0
- package/src/components/msa/DomainLegend.tsx +74 -0
- package/src/components/msa/MSACanvasBlock.tsx +22 -4
- package/src/components/msa/MSAPanel.tsx +2 -0
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +73 -17
- package/src/components/msa/renderMSABlock.ts +5 -11
- package/src/components/msa/renderMSAMouseover.ts +32 -4
- package/src/components/renderCtx.ts +1 -0
- package/src/components/tracks/renderTracksSvg.ts +4 -4
- package/src/components/tree/renderTreeCanvas.ts +5 -1
- package/src/constants.ts +18 -0
- package/src/createPaletteMap.ts +18 -5
- package/src/hierarchy.ts +4 -1
- package/src/launchInterProScan.ts +3 -1
- package/src/model/msaModel.ts +3 -1
- package/src/model.ts +137 -36
- package/src/neighborJoining.ts +44 -31
- package/src/renderDomainLegendSvg.test.tsx +134 -0
- package/src/renderToSvg.tsx +210 -147
- package/src/segmentOverlay.test.ts +70 -0
- package/src/version.ts +1 -1
- package/bundle/index.js.LICENSE.txt +0 -100
- package/dist/components/util.d.ts +0 -1
- package/dist/components/util.js +0 -7
- package/dist/components/util.js.map +0 -1
- package/dist/webpack.js.map +0 -1
- package/src/components/util.ts +0 -9
- /package/dist/{webpack.d.ts → umd.d.ts} +0 -0
- /package/src/{webpack.ts → umd.ts} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getVisibleLeaves } from './getVisibleLeaves.ts'
|
|
2
|
+
import { subFeatureRowHeight } from '../../constants.ts'
|
|
2
3
|
|
|
3
4
|
import type { HierarchyNode } from '../../hierarchy.ts'
|
|
4
5
|
import type { MsaViewModel } from '../../model.ts'
|
|
@@ -53,38 +54,93 @@ function drawTiles({
|
|
|
53
54
|
rowHeight,
|
|
54
55
|
fillPalette,
|
|
55
56
|
strokePalette,
|
|
57
|
+
segmentLabels,
|
|
58
|
+
showMsaLetters,
|
|
56
59
|
tidyFilteredGatheredInterProAnnotations,
|
|
57
60
|
} = model
|
|
61
|
+
const h = subFeatureRows ? subFeatureRowHeight : rowHeight
|
|
62
|
+
// exon numbers label the bands only when residue letters aren't drawn (zoomed
|
|
63
|
+
// out); when letters show, the alternating shades alone mark the boundaries
|
|
64
|
+
// and a number would collide with the sequence
|
|
65
|
+
const drawSegmentLabels = !showMsaLetters && !subFeatureRows && h >= 9
|
|
58
66
|
|
|
59
67
|
for (let i = 0, l1 = visibleLeaves.length; i < l1; i++) {
|
|
60
68
|
const node = visibleLeaves[i]!
|
|
61
|
-
const {
|
|
62
|
-
|
|
63
|
-
data: { name },
|
|
64
|
-
} = node
|
|
65
|
-
const y = x!
|
|
66
|
-
|
|
69
|
+
const { name } = node.data
|
|
70
|
+
const y = node.x!
|
|
67
71
|
const entry = tidyFilteredGatheredInterProAnnotations[name]
|
|
68
72
|
|
|
69
73
|
if (entry) {
|
|
70
74
|
for (let j = 0, l2 = entry.length; j < l2; j++) {
|
|
71
|
-
const { start, end, accession } = entry[j]!
|
|
75
|
+
const { start, end, accession, strand } = entry[j]!
|
|
72
76
|
// Convert sequence positions to visible column positions
|
|
73
77
|
// seqPos is 1-based from InterPro, so subtract 1 for 0-based
|
|
74
78
|
const m1 = model.seqPosToVisibleCol(name, start - 1)
|
|
75
79
|
const m2 = model.seqPosToVisibleCol(name, end)
|
|
76
|
-
if (m1
|
|
77
|
-
|
|
80
|
+
if (m1 !== undefined && m2 !== undefined) {
|
|
81
|
+
const x = m1 * colWidth
|
|
82
|
+
const t = y - rowHeight + (subFeatureRows ? j * h : 0)
|
|
83
|
+
const lw = colWidth * (m2 - m1)
|
|
84
|
+
ctx.fillStyle = fillPalette[accession]!
|
|
85
|
+
ctx.strokeStyle = strokePalette[accession]!
|
|
86
|
+
if (strand === undefined) {
|
|
87
|
+
ctx.fillRect(x, t, lw, h)
|
|
88
|
+
ctx.strokeRect(x, t, lw, h)
|
|
89
|
+
// segment (exon) number drawn once per band, on the top visible row,
|
|
90
|
+
// so it reads as a column header for the whole band
|
|
91
|
+
const label = drawSegmentLabels ? segmentLabels.get(accession) : undefined
|
|
92
|
+
if (label !== undefined && i === 0) {
|
|
93
|
+
const fontSize = Math.min(h - 2, 11)
|
|
94
|
+
ctx.font = `${fontSize}px sans-serif`
|
|
95
|
+
if (ctx.measureText(label).width + 2 <= lw) {
|
|
96
|
+
ctx.fillStyle = '#222'
|
|
97
|
+
ctx.textAlign = 'center'
|
|
98
|
+
ctx.textBaseline = 'middle'
|
|
99
|
+
ctx.fillText(label, x + lw / 2, t + h / 2)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
drawGeneArrow({ ctx, x, t, w: lw, h, strand })
|
|
104
|
+
}
|
|
78
105
|
}
|
|
79
|
-
const x = m1 * colWidth
|
|
80
|
-
ctx.fillStyle = fillPalette[accession]!
|
|
81
|
-
ctx.strokeStyle = strokePalette[accession]!
|
|
82
|
-
const h = subFeatureRows ? 4 : rowHeight
|
|
83
|
-
const t = y - rowHeight + (subFeatureRows ? j * h : 0)
|
|
84
|
-
const lw = colWidth * (m2 - m1)
|
|
85
|
-
ctx.fillRect(x, t, lw, h)
|
|
86
|
-
ctx.strokeRect(x, t, lw, h)
|
|
87
106
|
}
|
|
88
107
|
}
|
|
89
108
|
}
|
|
90
109
|
}
|
|
110
|
+
|
|
111
|
+
// A gene arrow: a full-width rectangular body spanning the feature's
|
|
112
|
+
// start..end columns, plus a triangular head that points *beyond* that end in
|
|
113
|
+
// the strand direction (right for +, left for -). Keeping the body aligned to
|
|
114
|
+
// the exact start/end columns means + and - strand features read as having the
|
|
115
|
+
// same boundaries; the arrow lives outside them purely to show transcription
|
|
116
|
+
// direction, preserving the column-by-column homology down the rows.
|
|
117
|
+
function drawGeneArrow({
|
|
118
|
+
ctx,
|
|
119
|
+
x,
|
|
120
|
+
t,
|
|
121
|
+
w,
|
|
122
|
+
h,
|
|
123
|
+
strand,
|
|
124
|
+
}: {
|
|
125
|
+
ctx: RenderCtx
|
|
126
|
+
x: number
|
|
127
|
+
t: number
|
|
128
|
+
w: number
|
|
129
|
+
h: number
|
|
130
|
+
strand: number
|
|
131
|
+
}) {
|
|
132
|
+
// body spans bodyStart..bodyEnd (the exact columns); the head extends one
|
|
133
|
+
// row-height past bodyEnd in the strand direction
|
|
134
|
+
const dir = strand > 0 ? 1 : -1
|
|
135
|
+
const bodyStart = strand > 0 ? x : x + w
|
|
136
|
+
const bodyEnd = strand > 0 ? x + w : x
|
|
137
|
+
ctx.beginPath()
|
|
138
|
+
ctx.moveTo(bodyStart, t)
|
|
139
|
+
ctx.lineTo(bodyEnd, t)
|
|
140
|
+
ctx.lineTo(bodyEnd + dir * h, t + h / 2)
|
|
141
|
+
ctx.lineTo(bodyEnd, t + h)
|
|
142
|
+
ctx.lineTo(bodyStart, t + h)
|
|
143
|
+
ctx.closePath()
|
|
144
|
+
ctx.fill()
|
|
145
|
+
ctx.stroke()
|
|
146
|
+
}
|
|
@@ -46,6 +46,7 @@ export function renderMSABlock({
|
|
|
46
46
|
ctx.scale(k, k)
|
|
47
47
|
ctx.translate(-offsetX, rowHeight / 2 - offsetY)
|
|
48
48
|
ctx.textAlign = 'center'
|
|
49
|
+
ctx.textBaseline = 'alphabetic'
|
|
49
50
|
setFontSize(ctx, fontSize, !bgColor)
|
|
50
51
|
|
|
51
52
|
const { xStart, xEnd } = visibleColRange({
|
|
@@ -65,7 +66,6 @@ export function renderMSABlock({
|
|
|
65
66
|
ctx,
|
|
66
67
|
theme,
|
|
67
68
|
contrastScheme,
|
|
68
|
-
offsetX,
|
|
69
69
|
xStart,
|
|
70
70
|
xEnd,
|
|
71
71
|
visibleLeaves,
|
|
@@ -75,7 +75,6 @@ export function renderMSABlock({
|
|
|
75
75
|
drawText({
|
|
76
76
|
model,
|
|
77
77
|
ctx,
|
|
78
|
-
offsetX,
|
|
79
78
|
xStart,
|
|
80
79
|
xEnd,
|
|
81
80
|
visibleLeaves,
|
|
@@ -94,7 +93,6 @@ export function renderMSABlock({
|
|
|
94
93
|
|
|
95
94
|
function drawTilesAndText({
|
|
96
95
|
model,
|
|
97
|
-
offsetX,
|
|
98
96
|
ctx,
|
|
99
97
|
theme,
|
|
100
98
|
contrastScheme,
|
|
@@ -104,7 +102,6 @@ function drawTilesAndText({
|
|
|
104
102
|
referenceSeq,
|
|
105
103
|
}: {
|
|
106
104
|
model: MsaViewModel
|
|
107
|
-
offsetX: number
|
|
108
105
|
theme: Theme
|
|
109
106
|
ctx: RenderCtx
|
|
110
107
|
contrastScheme: Record<string, string>
|
|
@@ -128,11 +125,10 @@ function drawTilesAndText({
|
|
|
128
125
|
|
|
129
126
|
const isClustalX = colorSchemeName === 'clustalx_protein_dynamic'
|
|
130
127
|
const isPercentIdentity = colorSchemeName === 'percent_identity_dynamic'
|
|
131
|
-
|
|
132
|
-
if (!drawBgTiles && !showMsaLetters) {
|
|
128
|
+
if (!bgColor && !showMsaLetters) {
|
|
133
129
|
return
|
|
134
130
|
}
|
|
135
|
-
const offsetXAligned =
|
|
131
|
+
const offsetXAligned = xStart * colWidth
|
|
136
132
|
const halfColWidth = colWidth / 2
|
|
137
133
|
const quarterRowHeight = rowHeight / 4
|
|
138
134
|
|
|
@@ -163,7 +159,7 @@ function drawTilesAndText({
|
|
|
163
159
|
color = colorScheme[letter]
|
|
164
160
|
}
|
|
165
161
|
|
|
166
|
-
if (
|
|
162
|
+
if (bgColor) {
|
|
167
163
|
ctx.fillStyle = isMatchingReference
|
|
168
164
|
? theme.palette.action.hover
|
|
169
165
|
: color || theme.palette.background.default
|
|
@@ -190,14 +186,12 @@ function drawTilesAndText({
|
|
|
190
186
|
// so we only need to draw text here.
|
|
191
187
|
function drawText({
|
|
192
188
|
model,
|
|
193
|
-
offsetX,
|
|
194
189
|
ctx,
|
|
195
190
|
visibleLeaves,
|
|
196
191
|
xStart,
|
|
197
192
|
xEnd,
|
|
198
193
|
referenceSeq,
|
|
199
194
|
}: {
|
|
200
|
-
offsetX: number
|
|
201
195
|
model: MsaViewModel
|
|
202
196
|
ctx: RenderCtx
|
|
203
197
|
visibleLeaves: HierarchyNode<NodeWithIdsAndLength>[]
|
|
@@ -210,7 +204,7 @@ function drawText({
|
|
|
210
204
|
if (!showMsaLetters) {
|
|
211
205
|
return
|
|
212
206
|
}
|
|
213
|
-
const offsetXAligned =
|
|
207
|
+
const offsetXAligned = xStart * colWidth
|
|
214
208
|
const halfColWidth = colWidth / 2
|
|
215
209
|
const quarterRowHeight = rowHeight / 4
|
|
216
210
|
// note: -rowHeight/4 matches +rowHeight/4 in tree
|
|
@@ -2,9 +2,31 @@ import type { MsaViewModel } from '../../model.ts'
|
|
|
2
2
|
|
|
3
3
|
const hoverColor = 'rgba(0,0,0,0.15)'
|
|
4
4
|
const highlightColor = 'rgba(128,128,0,0.2)'
|
|
5
|
+
// the persistent highlightColumns overlay: a stronger fill plus a solid border
|
|
6
|
+
// so a domain/motif band reads clearly over the colored alignment cells (the
|
|
7
|
+
// faint hover-style wash alone is invisible against clustalx coloring)
|
|
8
|
+
const highlightColumnsFill = 'rgba(255,140,0,0.28)'
|
|
9
|
+
const highlightColumnsBorder = 'rgba(210,90,0,0.95)'
|
|
5
10
|
const referenceColor = 'rgba(0,128,255,0.3)' // Blue highlight for reference row
|
|
6
11
|
const multiRowHoverColor = 'rgba(255,165,0,0.15)' // Orange highlight for multi-row tree hover
|
|
7
12
|
|
|
13
|
+
// Collapse sorted column indices into contiguous [start,end] runs so a run of
|
|
14
|
+
// highlighted columns draws as one bordered band rather than per-column slices
|
|
15
|
+
// (which would draw internal borders).
|
|
16
|
+
function contiguousRuns(columns: number[]) {
|
|
17
|
+
const sorted = [...columns].sort((a, b) => a - b)
|
|
18
|
+
const runs: { start: number; end: number }[] = []
|
|
19
|
+
for (const col of sorted) {
|
|
20
|
+
const last = runs.at(-1)
|
|
21
|
+
if (last && col === last.end + 1) {
|
|
22
|
+
last.end = col
|
|
23
|
+
} else {
|
|
24
|
+
runs.push({ start: col, end: col })
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return runs
|
|
28
|
+
}
|
|
29
|
+
|
|
8
30
|
export function renderMouseover({
|
|
9
31
|
ctx,
|
|
10
32
|
model,
|
|
@@ -54,11 +76,17 @@ export function renderMouseover({
|
|
|
54
76
|
}
|
|
55
77
|
}
|
|
56
78
|
|
|
57
|
-
// Highlight multiple columns
|
|
79
|
+
// Highlight multiple columns — draw each contiguous run as a filled, bordered
|
|
80
|
+
// band so a domain/motif highlight is clearly visible over the alignment
|
|
58
81
|
if (highlightedColumns?.length) {
|
|
59
|
-
ctx.
|
|
60
|
-
for (const
|
|
61
|
-
|
|
82
|
+
ctx.lineWidth = 2
|
|
83
|
+
for (const { start, end } of contiguousRuns(highlightedColumns)) {
|
|
84
|
+
const x = start * colWidth + scrollX
|
|
85
|
+
const w = (end - start + 1) * colWidth
|
|
86
|
+
ctx.fillStyle = highlightColumnsFill
|
|
87
|
+
ctx.fillRect(x, 0, w, height)
|
|
88
|
+
ctx.strokeStyle = highlightColumnsBorder
|
|
89
|
+
ctx.strokeRect(x, 0, w, height)
|
|
62
90
|
}
|
|
63
91
|
}
|
|
64
92
|
|
|
@@ -65,13 +65,13 @@ export function drawTextTrackContent({
|
|
|
65
65
|
|
|
66
66
|
for (let i = 0; str && i < str.length; i++) {
|
|
67
67
|
const letter = str[i]!
|
|
68
|
-
const
|
|
68
|
+
const upper = letter.toUpperCase()
|
|
69
69
|
if (bgColor) {
|
|
70
|
-
const x =
|
|
71
|
-
ctx.fillStyle =
|
|
70
|
+
const x = (xStart + i) * colWidth
|
|
71
|
+
ctx.fillStyle = colorScheme[upper] || 'white'
|
|
72
72
|
ctx.fillRect(x, 0, colWidth, rowHeight)
|
|
73
73
|
if (rowHeight >= 10 && colWidth >= rowHeight / 2) {
|
|
74
|
-
ctx.fillStyle = contrastScheme[
|
|
74
|
+
ctx.fillStyle = contrastScheme[upper] || 'black'
|
|
75
75
|
ctx.fillText(letter, x + colWidth / 2, rowHeight / 2 + 1)
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -29,6 +29,9 @@ function getNodeX(
|
|
|
29
29
|
if (showBranchLen) {
|
|
30
30
|
return node.len
|
|
31
31
|
}
|
|
32
|
+
if (maxDepthToLeaf === 0) {
|
|
33
|
+
return 0
|
|
34
|
+
}
|
|
32
35
|
const depthToLeaf = calcDepthToLeaf(node)
|
|
33
36
|
return ((maxDepthToLeaf - depthToLeaf) / maxDepthToLeaf) * maxBranchLen
|
|
34
37
|
}
|
|
@@ -134,7 +137,8 @@ export function renderCollapsedTriangles({
|
|
|
134
137
|
if (collapsed.includes(id)) {
|
|
135
138
|
const apexX = getNodeX(node, showBranchLen, maxBranchLen, maxDepthToLeaf)
|
|
136
139
|
const y = node.x!
|
|
137
|
-
const inBlock =
|
|
140
|
+
const inBlock =
|
|
141
|
+
y > offsetY - extendBounds && y < offsetY + by + extendBounds
|
|
138
142
|
// in cladogram mode the hidden tips align at the right edge, otherwise use
|
|
139
143
|
// the branch-length extent recorded in the model's hierarchy getter
|
|
140
144
|
const baseX = showBranchLen
|
package/src/constants.ts
CHANGED
|
@@ -9,6 +9,24 @@ export const defaultShowDomains = false
|
|
|
9
9
|
export const defaultHideGaps = true
|
|
10
10
|
export const defaultAllowedGappyness = 100
|
|
11
11
|
export const defaultSubFeatureRows = false
|
|
12
|
+
// row height for each stacked feature when subFeatureRows is on
|
|
13
|
+
export const subFeatureRowHeight = 4
|
|
14
|
+
|
|
15
|
+
// Feature types that are ordinal *segments* of a single transcript (exons and
|
|
16
|
+
// the like) rather than categorical domains. Their identity is their position,
|
|
17
|
+
// so the overlay alternates two shades to mark boundaries and labels them by
|
|
18
|
+
// number, instead of assigning every one a distinct hue + legend row.
|
|
19
|
+
export const segmentFeatureTypes = new Set([
|
|
20
|
+
'exon',
|
|
21
|
+
'CDS',
|
|
22
|
+
'five_prime_UTR',
|
|
23
|
+
'three_prime_UTR',
|
|
24
|
+
'UTR',
|
|
25
|
+
'intron',
|
|
26
|
+
])
|
|
27
|
+
|
|
28
|
+
// the two shades alternated across adjacent segments (exons)
|
|
29
|
+
export const segmentShades = ['#9fb6d4', '#d4dcea']
|
|
12
30
|
export const defaultDrawMsaLetters = true
|
|
13
31
|
export const defaultScrollZoom = false
|
|
14
32
|
|
package/src/createPaletteMap.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
import { colord } from 'colord'
|
|
2
|
+
|
|
1
3
|
import palettes from './ggplotPalettes.ts'
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
|
-
* Creates a map from keys to colors
|
|
5
|
-
*
|
|
6
|
+
* Creates a map from keys to colors. Up to the largest ggplot palette (8 keys)
|
|
7
|
+
* we use the hand-picked ggplot colors; beyond that — e.g. a gene-structure
|
|
8
|
+
* overlay with one feature per exon — we generate evenly spaced HSL hues so
|
|
9
|
+
* every key still gets a distinct, stable color instead of running off the end
|
|
10
|
+
* of the palette.
|
|
6
11
|
*/
|
|
7
12
|
export function createPaletteMap(keys: string[]) {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
const n = keys.length
|
|
14
|
+
if (n <= palettes.length) {
|
|
15
|
+
const palette = palettes[n - 1]!
|
|
16
|
+
return Object.fromEntries(keys.map((key, i) => [key, palette[i]!]))
|
|
17
|
+
}
|
|
18
|
+
return Object.fromEntries(
|
|
19
|
+
keys.map((key, i) => [
|
|
20
|
+
key,
|
|
21
|
+
colord({ h: (i * 360) / n, s: 60, l: 60 }).toHex(),
|
|
22
|
+
]),
|
|
23
|
+
)
|
|
11
24
|
}
|
package/src/hierarchy.ts
CHANGED
|
@@ -269,7 +269,10 @@ export function collapsedSubtreeLengthExtent<T extends { length?: number }>(
|
|
|
269
269
|
const kids = n.children ?? n._children
|
|
270
270
|
if (kids?.length) {
|
|
271
271
|
for (const child of kids) {
|
|
272
|
-
stack.push({
|
|
272
|
+
stack.push({
|
|
273
|
+
node: child,
|
|
274
|
+
acc: acc + Math.max(child.data.length ?? 0, 0),
|
|
275
|
+
})
|
|
273
276
|
}
|
|
274
277
|
} else {
|
|
275
278
|
min = Math.min(min, acc)
|
|
@@ -13,9 +13,11 @@ export interface InterProScanResults {
|
|
|
13
13
|
name: string
|
|
14
14
|
description: string
|
|
15
15
|
accession: string
|
|
16
|
+
// original GFF feature type (exon, CDS, ...) when sourced from GFF
|
|
17
|
+
featureType?: string
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
|
-
locations: { start: number; end: number }[]
|
|
20
|
+
locations: { start: number; end: number; strand?: number }[]
|
|
19
21
|
}[]
|
|
20
22
|
xref: { id: string }[]
|
|
21
23
|
}
|
package/src/model/msaModel.ts
CHANGED
|
@@ -29,7 +29,9 @@ export function MSAModelF() {
|
|
|
29
29
|
* force the MSA data to be parsed as a specific format instead of relying
|
|
30
30
|
* on auto-detection (which is ambiguous between e.g. fasta and a3m)
|
|
31
31
|
*/
|
|
32
|
-
msaFormat: types.maybe(
|
|
32
|
+
msaFormat: types.maybe(
|
|
33
|
+
types.enumeration<MSAFormat>('MSAFormat', msaFormats),
|
|
34
|
+
),
|
|
33
35
|
})
|
|
34
36
|
.actions(self => ({
|
|
35
37
|
/**
|