jbrowse-plugin-mafviewer 1.4.3 → 1.4.6
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/README.md +1 -1
- package/dist/BigMafAdapter/BigMafAdapter.js +4 -5
- package/dist/BigMafAdapter/BigMafAdapter.js.map +1 -1
- package/dist/BigMafAdapter/configSchema.d.ts +2 -2
- package/dist/LinearMafDisplay/components/LinearMafDisplayComponent.js +39 -109
- package/dist/LinearMafDisplay/components/LinearMafDisplayComponent.js.map +1 -1
- package/dist/LinearMafDisplay/components/MAFTooltip.d.ts +0 -3
- package/dist/LinearMafDisplay/components/MAFTooltip.js.map +1 -1
- package/dist/LinearMafDisplay/components/MsaHighlightOverlay.d.ts +9 -0
- package/dist/LinearMafDisplay/components/MsaHighlightOverlay.js +34 -0
- package/dist/LinearMafDisplay/components/MsaHighlightOverlay.js.map +1 -0
- package/dist/LinearMafDisplay/components/Sidebar/ColorLegend.js +2 -2
- package/dist/LinearMafDisplay/components/Sidebar/ColorLegend.js.map +1 -1
- package/dist/LinearMafDisplay/components/Sidebar/RectBg.d.ts +1 -1
- package/dist/LinearMafDisplay/components/Sidebar/RectBg.js +2 -3
- package/dist/LinearMafDisplay/components/Sidebar/RectBg.js.map +1 -1
- package/dist/LinearMafDisplay/components/Sidebar/SvgWrapper.js +81 -11
- package/dist/LinearMafDisplay/components/Sidebar/SvgWrapper.js.map +1 -1
- package/dist/LinearMafDisplay/components/Sidebar/Tree.js +30 -9
- package/dist/LinearMafDisplay/components/Sidebar/Tree.js.map +1 -1
- package/dist/LinearMafDisplay/components/Sidebar/YScaleBars.d.ts +0 -1
- package/dist/LinearMafDisplay/components/Sidebar/YScaleBars.js.map +1 -1
- package/dist/LinearMafDisplay/components/useDragSelection.d.ts +25 -0
- package/dist/LinearMafDisplay/components/useDragSelection.js +103 -0
- package/dist/LinearMafDisplay/components/useDragSelection.js.map +1 -0
- package/dist/LinearMafDisplay/configSchema.d.ts +3 -30
- package/dist/LinearMafDisplay/renderSvg.js +1 -1
- package/dist/LinearMafDisplay/renderSvg.js.map +1 -1
- package/dist/LinearMafDisplay/stateModel.d.ts +1090 -102
- package/dist/LinearMafDisplay/stateModel.js +156 -17
- package/dist/LinearMafDisplay/stateModel.js.map +1 -1
- package/dist/LinearMafDisplay/types.d.ts +2 -2
- package/dist/LinearMafDisplay/util.d.ts +6 -0
- package/dist/LinearMafDisplay/util.js +28 -6
- package/dist/LinearMafDisplay/util.js.map +1 -1
- package/dist/LinearMafRenderer/LinearMafRenderer.d.ts +43 -10
- package/dist/LinearMafRenderer/LinearMafRenderer.js +1 -1
- package/dist/LinearMafRenderer/LinearMafRenderer.js.map +1 -1
- package/dist/LinearMafRenderer/components/LinearMafRendering.d.ts +14 -5
- package/dist/LinearMafRenderer/components/LinearMafRendering.js +40 -20
- package/dist/LinearMafRenderer/components/LinearMafRendering.js.map +1 -1
- package/dist/LinearMafRenderer/configSchema.d.ts +1 -6
- package/dist/LinearMafRenderer/configSchema.js +1 -6
- package/dist/LinearMafRenderer/configSchema.js.map +1 -1
- package/dist/LinearMafRenderer/makeImageData.js +6 -7
- package/dist/LinearMafRenderer/makeImageData.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/features.d.ts +0 -1
- package/dist/LinearMafRenderer/rendering/features.js +1 -14
- package/dist/LinearMafRenderer/rendering/features.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/insertions.d.ts +1 -1
- package/dist/LinearMafRenderer/rendering/insertions.js +10 -8
- package/dist/LinearMafRenderer/rendering/insertions.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/matches.d.ts +1 -1
- package/dist/LinearMafRenderer/rendering/matches.js +3 -15
- package/dist/LinearMafRenderer/rendering/matches.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/mismatches.d.ts +1 -1
- package/dist/LinearMafRenderer/rendering/mismatches.js +3 -3
- package/dist/LinearMafRenderer/rendering/spatialIndex.js +8 -2
- package/dist/LinearMafRenderer/rendering/spatialIndex.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/text.js +1 -3
- package/dist/LinearMafRenderer/rendering/text.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/types.d.ts +6 -5
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js +1 -1
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js.map +1 -1
- package/dist/MafAddTrackWorkflow/index.js +1 -1
- package/dist/MafAddTrackWorkflow/index.js.map +1 -1
- package/dist/MafGetSequences/MafGetSequences.d.ts +1 -0
- package/dist/MafGetSequences/MafGetSequences.js +2 -1
- package/dist/MafGetSequences/MafGetSequences.js.map +1 -1
- package/dist/MafSequenceWidget/LabelsCanvas.d.ts +8 -0
- package/dist/MafSequenceWidget/LabelsCanvas.js +37 -0
- package/dist/MafSequenceWidget/LabelsCanvas.js.map +1 -0
- package/dist/MafSequenceWidget/MafSequenceHoverHighlight.d.ts +6 -0
- package/dist/MafSequenceWidget/MafSequenceHoverHighlight.js +52 -0
- package/dist/MafSequenceWidget/MafSequenceHoverHighlight.js.map +1 -0
- package/dist/MafSequenceWidget/MafSequenceHoverHighlightExtension.d.ts +2 -0
- package/dist/MafSequenceWidget/MafSequenceHoverHighlightExtension.js +12 -0
- package/dist/MafSequenceWidget/MafSequenceHoverHighlightExtension.js.map +1 -0
- package/dist/MafSequenceWidget/MafSequenceWidget.d.ts +6 -0
- package/dist/MafSequenceWidget/MafSequenceWidget.js +189 -0
- package/dist/MafSequenceWidget/MafSequenceWidget.js.map +1 -0
- package/dist/MafSequenceWidget/SequenceCanvas.d.ts +12 -0
- package/dist/MafSequenceWidget/SequenceCanvas.js +86 -0
- package/dist/MafSequenceWidget/SequenceCanvas.js.map +1 -0
- package/dist/MafSequenceWidget/SequenceDisplay.d.ts +12 -0
- package/dist/MafSequenceWidget/SequenceDisplay.js +117 -0
- package/dist/MafSequenceWidget/SequenceDisplay.js.map +1 -0
- package/dist/MafSequenceWidget/SequenceTooltip.d.ts +11 -0
- package/dist/MafSequenceWidget/SequenceTooltip.js +39 -0
- package/dist/MafSequenceWidget/SequenceTooltip.js.map +1 -0
- package/dist/MafSequenceWidget/baseColors.d.ts +3 -0
- package/dist/MafSequenceWidget/baseColors.js +64 -0
- package/dist/MafSequenceWidget/baseColors.js.map +1 -0
- package/dist/MafSequenceWidget/colToGenomePos.d.ts +13 -0
- package/dist/MafSequenceWidget/colToGenomePos.js +32 -0
- package/dist/MafSequenceWidget/colToGenomePos.js.map +1 -0
- package/dist/MafSequenceWidget/colToGenomePos.test.d.ts +1 -0
- package/dist/MafSequenceWidget/colToGenomePos.test.js +136 -0
- package/dist/MafSequenceWidget/colToGenomePos.test.js.map +1 -0
- package/dist/MafSequenceWidget/configSchema.d.ts +1 -0
- package/dist/MafSequenceWidget/configSchema.js +3 -0
- package/dist/MafSequenceWidget/configSchema.js.map +1 -0
- package/dist/MafSequenceWidget/constants.d.ts +4 -0
- package/dist/MafSequenceWidget/constants.js +5 -0
- package/dist/MafSequenceWidget/constants.js.map +1 -0
- package/dist/MafSequenceWidget/index.d.ts +2 -0
- package/dist/MafSequenceWidget/index.js +16 -0
- package/dist/MafSequenceWidget/index.js.map +1 -0
- package/dist/MafSequenceWidget/stateModelFactory.d.ts +67 -0
- package/dist/MafSequenceWidget/stateModelFactory.js +21 -0
- package/dist/MafSequenceWidget/stateModelFactory.js.map +1 -0
- package/dist/MafTabixAdapter/MafTabixAdapter.js +4 -35
- package/dist/MafTabixAdapter/MafTabixAdapter.js.map +1 -1
- package/dist/MafTabixAdapter/configSchema.d.ts +4 -4
- package/dist/MafTrack/configSchema.d.ts +16 -11
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/jbrowse-plugin-mafviewer.umd.production.min.js +12 -24
- package/dist/jbrowse-plugin-mafviewer.umd.production.min.js.map +4 -4
- package/dist/util/clipboard.d.ts +2 -0
- package/dist/util/clipboard.js +28 -0
- package/dist/util/clipboard.js.map +1 -0
- package/dist/util/fastaUtils.d.ts +2 -1
- package/dist/util/fastaUtils.js +93 -50
- package/dist/util/fastaUtils.js.map +1 -1
- package/dist/util/fastaUtils.test.js +190 -0
- package/dist/util/fastaUtils.test.js.map +1 -1
- package/dist/util/parseAssemblyName.d.ts +32 -0
- package/dist/util/parseAssemblyName.js +87 -0
- package/dist/util/parseAssemblyName.js.map +1 -0
- package/dist/util/parseAssemblyName.test.d.ts +1 -0
- package/dist/util/parseAssemblyName.test.js +269 -0
- package/dist/util/parseAssemblyName.test.js.map +1 -0
- package/package.json +12 -12
- package/src/BigMafAdapter/BigMafAdapter.ts +5 -5
- package/src/LinearMafDisplay/components/LinearMafDisplayComponent.tsx +63 -145
- package/src/LinearMafDisplay/components/MAFTooltip.tsx +0 -3
- package/src/LinearMafDisplay/components/MsaHighlightOverlay.tsx +62 -0
- package/src/LinearMafDisplay/components/Sidebar/ColorLegend.tsx +2 -6
- package/src/LinearMafDisplay/components/Sidebar/RectBg.tsx +8 -3
- package/src/LinearMafDisplay/components/Sidebar/SvgWrapper.tsx +117 -15
- package/src/LinearMafDisplay/components/Sidebar/Tree.tsx +53 -8
- package/src/LinearMafDisplay/components/Sidebar/YScaleBars.tsx +0 -1
- package/src/LinearMafDisplay/components/useDragSelection.ts +159 -0
- package/src/LinearMafDisplay/renderSvg.tsx +1 -1
- package/src/LinearMafDisplay/stateModel.ts +215 -20
- package/src/LinearMafDisplay/types.ts +2 -2
- package/src/LinearMafDisplay/util.ts +35 -7
- package/src/LinearMafRenderer/LinearMafRenderer.ts +3 -5
- package/src/LinearMafRenderer/components/LinearMafRendering.tsx +67 -33
- package/src/LinearMafRenderer/configSchema.ts +1 -6
- package/src/LinearMafRenderer/makeImageData.ts +5 -14
- package/src/LinearMafRenderer/rendering/features.ts +2 -36
- package/src/LinearMafRenderer/rendering/insertions.ts +13 -8
- package/src/LinearMafRenderer/rendering/matches.ts +2 -27
- package/src/LinearMafRenderer/rendering/mismatches.ts +3 -3
- package/src/LinearMafRenderer/rendering/spatialIndex.ts +9 -2
- package/src/LinearMafRenderer/rendering/text.ts +1 -2
- package/src/LinearMafRenderer/rendering/types.ts +8 -5
- package/src/MafAddTrackWorkflow/AddTrackWorkflow.tsx +1 -1
- package/src/MafAddTrackWorkflow/index.ts +1 -1
- package/src/MafGetSequences/MafGetSequences.ts +10 -2
- package/src/MafSequenceWidget/LabelsCanvas.tsx +58 -0
- package/src/MafSequenceWidget/MafSequenceHoverHighlight.tsx +83 -0
- package/src/MafSequenceWidget/MafSequenceHoverHighlightExtension.tsx +24 -0
- package/src/MafSequenceWidget/MafSequenceWidget.tsx +294 -0
- package/src/MafSequenceWidget/SequenceCanvas.tsx +136 -0
- package/src/MafSequenceWidget/SequenceDisplay.tsx +188 -0
- package/src/MafSequenceWidget/SequenceTooltip.tsx +70 -0
- package/src/MafSequenceWidget/baseColors.ts +76 -0
- package/src/MafSequenceWidget/colToGenomePos.test.ts +166 -0
- package/src/MafSequenceWidget/colToGenomePos.ts +40 -0
- package/src/MafSequenceWidget/configSchema.ts +3 -0
- package/src/MafSequenceWidget/constants.ts +4 -0
- package/src/MafSequenceWidget/index.ts +24 -0
- package/src/MafSequenceWidget/stateModelFactory.ts +43 -0
- package/src/MafTabixAdapter/MafTabixAdapter.ts +12 -51
- package/src/index.ts +2 -0
- package/src/util/__snapshots__/fastaUtils.test.ts.snap +35 -0
- package/src/util/clipboard.ts +35 -0
- package/src/util/fastaUtils.test.ts +199 -0
- package/src/util/fastaUtils.ts +118 -51
- package/src/util/parseAssemblyName.test.ts +350 -0
- package/src/util/parseAssemblyName.ts +106 -0
- package/dist/LinearMafDisplay/components/GetSequenceDialog/GetSequenceDialog.d.ts +0 -11
- package/dist/LinearMafDisplay/components/GetSequenceDialog/GetSequenceDialog.js +0 -97
- package/dist/LinearMafDisplay/components/GetSequenceDialog/GetSequenceDialog.js.map +0 -1
- package/dist/LinearMafDisplay/components/util.d.ts +0 -1
- package/dist/LinearMafDisplay/components/util.js +0 -8
- package/dist/LinearMafDisplay/components/util.js.map +0 -1
- package/dist/LinearMafRenderer/components/util.d.ts +0 -1
- package/dist/LinearMafRenderer/components/util.js +0 -13
- package/dist/LinearMafRenderer/components/util.js.map +0 -1
- package/dist/util/fetchSequences.d.ts +0 -18
- package/dist/util/fetchSequences.js +0 -39
- package/dist/util/fetchSequences.js.map +0 -1
- package/dist/util/useSequences.d.ts +0 -21
- package/dist/util/useSequences.js +0 -64
- package/dist/util/useSequences.js.map +0 -1
- package/src/LinearMafDisplay/components/GetSequenceDialog/GetSequenceDialog.tsx +0 -175
- package/src/LinearMafDisplay/components/util.ts +0 -7
- package/src/LinearMafRenderer/components/util.ts +0 -13
- package/src/util/fetchSequences.ts +0 -57
- package/src/util/useSequences.ts +0 -90
|
@@ -20,7 +20,7 @@ export function processFeatureAlignment(
|
|
|
20
20
|
string,
|
|
21
21
|
AlignmentRecord
|
|
22
22
|
>
|
|
23
|
-
const referenceSeq = feature.get('seq').toLowerCase()
|
|
23
|
+
const referenceSeq = (feature.get('seq') as string).toLowerCase()
|
|
24
24
|
|
|
25
25
|
for (const [sampleId, alignmentData] of Object.entries(alignments)) {
|
|
26
26
|
const row = sampleToRowMap.get(sampleId)
|
|
@@ -33,16 +33,7 @@ export function processFeatureAlignment(
|
|
|
33
33
|
const rowTop = renderingContext.offset + renderingContext.rowHeight * row
|
|
34
34
|
|
|
35
35
|
renderGaps(renderingContext, alignment, referenceSeq, leftPx, rowTop)
|
|
36
|
-
renderMatches(
|
|
37
|
-
renderingContext,
|
|
38
|
-
alignment,
|
|
39
|
-
referenceSeq,
|
|
40
|
-
leftPx,
|
|
41
|
-
rowTop,
|
|
42
|
-
row,
|
|
43
|
-
alignmentData.start,
|
|
44
|
-
alignmentData.chr,
|
|
45
|
-
)
|
|
36
|
+
renderMatches(renderingContext, alignment, referenceSeq, leftPx, rowTop)
|
|
46
37
|
renderMismatches(
|
|
47
38
|
renderingContext,
|
|
48
39
|
alignment,
|
|
@@ -61,31 +52,6 @@ export function processFeatureAlignment(
|
|
|
61
52
|
leftPx,
|
|
62
53
|
rowTop,
|
|
63
54
|
)
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function processFeatureInsertions(
|
|
68
|
-
feature: Feature,
|
|
69
|
-
region: GenomicRegion,
|
|
70
|
-
bpPerPx: number,
|
|
71
|
-
sampleToRowMap: Map<string, number>,
|
|
72
|
-
renderingContext: RenderingContext,
|
|
73
|
-
) {
|
|
74
|
-
const [leftPx] = featureSpanPx(feature, region, bpPerPx)
|
|
75
|
-
const alignments = feature.get('alignments') as Record<
|
|
76
|
-
string,
|
|
77
|
-
AlignmentRecord
|
|
78
|
-
>
|
|
79
|
-
const referenceSeq = feature.get('seq').toLowerCase()
|
|
80
|
-
for (const [sampleId, alignmentData] of Object.entries(alignments)) {
|
|
81
|
-
const row = sampleToRowMap.get(sampleId)
|
|
82
|
-
if (row === undefined) {
|
|
83
|
-
continue
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const alignment = alignmentData.seq.toLowerCase()
|
|
87
|
-
const rowTop = renderingContext.offset + renderingContext.rowHeight * row
|
|
88
|
-
|
|
89
55
|
renderInsertions(
|
|
90
56
|
renderingContext,
|
|
91
57
|
alignment,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { measureText } from '@jbrowse/core/util'
|
|
2
2
|
|
|
3
|
-
import { fillRect
|
|
3
|
+
import { fillRect } from '../util'
|
|
4
4
|
import { addToSpatialIndex, shouldAddToSpatialIndex } from './spatialIndex'
|
|
5
5
|
import {
|
|
6
6
|
CHAR_SIZE_WIDTH,
|
|
@@ -23,12 +23,11 @@ export function renderInsertions(
|
|
|
23
23
|
leftPx: number,
|
|
24
24
|
rowTop: number,
|
|
25
25
|
bpPerPx: number,
|
|
26
|
-
|
|
26
|
+
rowIndex: number,
|
|
27
27
|
alignmentStart: number,
|
|
28
28
|
chr: string,
|
|
29
29
|
) {
|
|
30
|
-
const { ctx, scale, h, canvasWidth, rowHeight } = context
|
|
31
|
-
const { charHeight } = getCharWidthHeight()
|
|
30
|
+
const { ctx, scale, h, canvasWidth, rowHeight, charHeight } = context
|
|
32
31
|
|
|
33
32
|
for (
|
|
34
33
|
let i = 0, genomicOffset = 0, seqLength = alignment.length;
|
|
@@ -102,14 +101,17 @@ export function renderInsertions(
|
|
|
102
101
|
actualXPos = xPos
|
|
103
102
|
actualWidth = INSERTION_LINE_WIDTH
|
|
104
103
|
fillRect(ctx, actualXPos, rowTop, actualWidth, h, canvasWidth, 'purple')
|
|
104
|
+
|
|
105
|
+
// Always use a wider hit box for spatial index, even if visual is 1px
|
|
106
|
+
const hitBoxPadding = 2
|
|
107
|
+
actualXPos = xPos - hitBoxPadding
|
|
108
|
+
actualWidth = INSERTION_LINE_WIDTH + 2 * hitBoxPadding
|
|
109
|
+
|
|
105
110
|
if (
|
|
106
111
|
bpPerPx < HIGH_ZOOM_THRESHOLD &&
|
|
107
112
|
rowHeight > MIN_ROW_HEIGHT_FOR_BORDERS
|
|
108
113
|
) {
|
|
109
114
|
// Add horizontal borders for visibility at high zoom
|
|
110
|
-
// Note: borders extend the effective clickable area
|
|
111
|
-
actualXPos = xPos - INSERTION_BORDER_WIDTH
|
|
112
|
-
actualWidth = INSERTION_BORDER_HEIGHT
|
|
113
115
|
fillRect(
|
|
114
116
|
ctx,
|
|
115
117
|
xPos - INSERTION_BORDER_WIDTH,
|
|
@@ -131,6 +133,8 @@ export function renderInsertions(
|
|
|
131
133
|
|
|
132
134
|
// Add insertion to spatial index with actual rendered dimensions
|
|
133
135
|
// Insertions always bypass distance filter
|
|
136
|
+
const isLargeInsertion =
|
|
137
|
+
insertionSequence.length > LARGE_INSERTION_THRESHOLD
|
|
134
138
|
if (shouldAddToSpatialIndex(actualXPos, context, true)) {
|
|
135
139
|
addToSpatialIndex(
|
|
136
140
|
context,
|
|
@@ -142,8 +146,9 @@ export function renderInsertions(
|
|
|
142
146
|
pos: genomicOffset + alignmentStart,
|
|
143
147
|
chr,
|
|
144
148
|
base: insertionSequence,
|
|
145
|
-
|
|
149
|
+
rowIndex,
|
|
146
150
|
isInsertion: true,
|
|
151
|
+
isLargeInsertion,
|
|
147
152
|
},
|
|
148
153
|
)
|
|
149
154
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { fillRect } from '../util'
|
|
2
|
-
import { addToSpatialIndex, shouldAddToSpatialIndex } from './spatialIndex'
|
|
3
2
|
import { GAP_STROKE_OFFSET } from './types'
|
|
4
3
|
|
|
5
4
|
import type { RenderingContext } from './types'
|
|
@@ -10,9 +9,6 @@ export function renderMatches(
|
|
|
10
9
|
seq: string,
|
|
11
10
|
leftPx: number,
|
|
12
11
|
rowTop: number,
|
|
13
|
-
sampleId: number,
|
|
14
|
-
alignmentStart: number,
|
|
15
|
-
chr: string,
|
|
16
12
|
) {
|
|
17
13
|
if (context.showAllLetters) {
|
|
18
14
|
return
|
|
@@ -30,30 +26,9 @@ export function renderMatches(
|
|
|
30
26
|
if (seq[i] !== '-') {
|
|
31
27
|
// Only process non-gap positions in reference
|
|
32
28
|
const currentChar = alignment[i]
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
seq[i] === currentChar &&
|
|
36
|
-
currentChar !== '-' &&
|
|
37
|
-
currentChar !== ' '
|
|
38
|
-
) {
|
|
29
|
+
if (seq[i] === currentChar && currentChar !== ' ') {
|
|
30
|
+
const xPos = leftPx + scale * genomicOffset
|
|
39
31
|
fillRect(ctx, xPos, rowTop, scale + GAP_STROKE_OFFSET, h, canvasWidth)
|
|
40
|
-
|
|
41
|
-
// Add to spatial index if distance filter allows
|
|
42
|
-
if (shouldAddToSpatialIndex(xPos, context)) {
|
|
43
|
-
addToSpatialIndex(
|
|
44
|
-
context,
|
|
45
|
-
xPos,
|
|
46
|
-
rowTop,
|
|
47
|
-
xPos + context.scale + GAP_STROKE_OFFSET,
|
|
48
|
-
rowTop + context.h,
|
|
49
|
-
{
|
|
50
|
-
pos: genomicOffset + alignmentStart,
|
|
51
|
-
chr,
|
|
52
|
-
base: currentChar || '',
|
|
53
|
-
sampleId,
|
|
54
|
-
},
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
32
|
}
|
|
58
33
|
genomicOffset++
|
|
59
34
|
}
|
|
@@ -21,7 +21,7 @@ export function renderMismatches(
|
|
|
21
21
|
seq: string,
|
|
22
22
|
leftPx: number,
|
|
23
23
|
rowTop: number,
|
|
24
|
-
|
|
24
|
+
rowIndex: number,
|
|
25
25
|
alignmentStart: number,
|
|
26
26
|
chr: string,
|
|
27
27
|
) {
|
|
@@ -70,7 +70,7 @@ export function renderMismatches(
|
|
|
70
70
|
pos: genomicOffset + alignmentStart,
|
|
71
71
|
chr,
|
|
72
72
|
base: currentChar!,
|
|
73
|
-
|
|
73
|
+
rowIndex,
|
|
74
74
|
},
|
|
75
75
|
)
|
|
76
76
|
}
|
|
@@ -100,7 +100,7 @@ export function renderMismatches(
|
|
|
100
100
|
pos: genomicOffset + alignmentStart,
|
|
101
101
|
chr,
|
|
102
102
|
base: currentChar!,
|
|
103
|
-
|
|
103
|
+
rowIndex,
|
|
104
104
|
},
|
|
105
105
|
)
|
|
106
106
|
}
|
|
@@ -20,9 +20,16 @@ export function shouldAddToSpatialIndex(
|
|
|
20
20
|
context: RenderingContext,
|
|
21
21
|
bypassDistanceFilter = false,
|
|
22
22
|
): boolean {
|
|
23
|
+
if (bypassDistanceFilter) {
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Zoom-aware distance threshold: scale threshold based on zoom level
|
|
28
|
+
// At high zoom (small bpPerPx), use smaller threshold for more precision
|
|
29
|
+
// At low zoom (large bpPerPx), use larger threshold to reduce index size
|
|
23
30
|
return (
|
|
24
|
-
|
|
25
|
-
Math.
|
|
31
|
+
Math.abs(xPos - context.lastInsertedX) >
|
|
32
|
+
MIN_X_DISTANCE * Math.max(1, context.bpPerPx)
|
|
26
33
|
)
|
|
27
34
|
}
|
|
28
35
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getCharWidthHeight } from '../util'
|
|
2
1
|
import { CHAR_SIZE_WIDTH, VERTICAL_TEXT_OFFSET } from './types'
|
|
3
2
|
|
|
4
3
|
import type { RenderingContext } from './types'
|
|
@@ -34,8 +33,8 @@ export function renderText(
|
|
|
34
33
|
mismatchRendering,
|
|
35
34
|
contrastForBase,
|
|
36
35
|
showAsUpperCase,
|
|
36
|
+
charHeight,
|
|
37
37
|
} = context
|
|
38
|
-
const { charHeight } = getCharWidthHeight()
|
|
39
38
|
|
|
40
39
|
// Render text labels when zoomed in enough and row is tall enough
|
|
41
40
|
if (scale >= CHAR_SIZE_WIDTH) {
|
|
@@ -13,10 +13,7 @@ export const HIGH_BP_PER_PX_THRESHOLD = 10
|
|
|
13
13
|
export const INSERTION_BORDER_HEIGHT = 5
|
|
14
14
|
export const MIN_X_DISTANCE = 0.5
|
|
15
15
|
|
|
16
|
-
export
|
|
17
|
-
id: string
|
|
18
|
-
color?: string
|
|
19
|
-
}
|
|
16
|
+
export type { Sample } from '../../LinearMafDisplay/types'
|
|
20
17
|
|
|
21
18
|
export interface GenomicRegion {
|
|
22
19
|
start: number
|
|
@@ -28,8 +25,9 @@ export interface RenderedBase {
|
|
|
28
25
|
pos: number
|
|
29
26
|
chr: string
|
|
30
27
|
base: string
|
|
31
|
-
|
|
28
|
+
rowIndex: number
|
|
32
29
|
isInsertion?: boolean
|
|
30
|
+
isLargeInsertion?: boolean
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
/**
|
|
@@ -38,6 +36,7 @@ export interface RenderedBase {
|
|
|
38
36
|
export interface RenderingContext {
|
|
39
37
|
ctx: CanvasRenderingContext2D
|
|
40
38
|
scale: number
|
|
39
|
+
bpPerPx: number
|
|
41
40
|
canvasWidth: number
|
|
42
41
|
rowHeight: number
|
|
43
42
|
h: number
|
|
@@ -49,6 +48,10 @@ export interface RenderingContext {
|
|
|
49
48
|
mismatchRendering: boolean
|
|
50
49
|
showAsUpperCase: boolean
|
|
51
50
|
|
|
51
|
+
// Cached char dimensions
|
|
52
|
+
charWidth: number
|
|
53
|
+
charHeight: number
|
|
54
|
+
|
|
52
55
|
// RBush spatial index for efficient spatial queries
|
|
53
56
|
spatialIndex: RenderedBase[]
|
|
54
57
|
spatialIndexCoords: number[]
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
isSessionModelWithWidgets,
|
|
8
8
|
isSessionWithAddTracks,
|
|
9
9
|
} from '@jbrowse/core/util'
|
|
10
|
+
import { getRoot } from '@jbrowse/mobx-state-tree'
|
|
10
11
|
import {
|
|
11
12
|
Button,
|
|
12
13
|
FormControl,
|
|
@@ -17,7 +18,6 @@ import {
|
|
|
17
18
|
RadioGroup,
|
|
18
19
|
TextField,
|
|
19
20
|
} from '@mui/material'
|
|
20
|
-
import { getRoot } from 'mobx-state-tree'
|
|
21
21
|
import { makeStyles } from 'tss-react/mui'
|
|
22
22
|
|
|
23
23
|
import type { AddTrackModel } from '@jbrowse/plugin-data-management'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
2
|
import { AddTrackWorkflowType } from '@jbrowse/core/pluggableElementTypes'
|
|
3
|
-
import { types } from 'mobx-state-tree'
|
|
3
|
+
import { types } from '@jbrowse/mobx-state-tree'
|
|
4
4
|
|
|
5
5
|
import MultiMAFWidget from './AddTrackWorkflow'
|
|
6
6
|
|
|
@@ -21,6 +21,7 @@ export default class MafGetSequences extends RpcMethodTypeWithFiltersAndRenameRe
|
|
|
21
21
|
headers?: Record<string, string>
|
|
22
22
|
regions: Region[]
|
|
23
23
|
showAllLetters: boolean
|
|
24
|
+
includeInsertions?: boolean
|
|
24
25
|
},
|
|
25
26
|
rpcDriverClassName: string,
|
|
26
27
|
) {
|
|
@@ -28,8 +29,14 @@ export default class MafGetSequences extends RpcMethodTypeWithFiltersAndRenameRe
|
|
|
28
29
|
args,
|
|
29
30
|
rpcDriverClassName,
|
|
30
31
|
)
|
|
31
|
-
const {
|
|
32
|
-
|
|
32
|
+
const {
|
|
33
|
+
samples,
|
|
34
|
+
regions,
|
|
35
|
+
adapterConfig,
|
|
36
|
+
sessionId,
|
|
37
|
+
showAllLetters,
|
|
38
|
+
includeInsertions,
|
|
39
|
+
} = deserializedArgs
|
|
33
40
|
const dataAdapter = (
|
|
34
41
|
await getAdapter(this.pluginManager, sessionId, adapterConfig)
|
|
35
42
|
).dataAdapter as BaseFeatureDataAdapter
|
|
@@ -42,6 +49,7 @@ export default class MafGetSequences extends RpcMethodTypeWithFiltersAndRenameRe
|
|
|
42
49
|
samples,
|
|
43
50
|
regions,
|
|
44
51
|
showAllLetters,
|
|
52
|
+
includeInsertions,
|
|
45
53
|
})
|
|
46
54
|
}
|
|
47
55
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react'
|
|
2
|
+
|
|
3
|
+
import { useTheme } from '@mui/material'
|
|
4
|
+
|
|
5
|
+
import { CHAR_WIDTH, FONT, LABEL_PADDING, ROW_HEIGHT } from './constants'
|
|
6
|
+
|
|
7
|
+
import type { Sample } from '../LinearMafDisplay/types'
|
|
8
|
+
|
|
9
|
+
interface LabelsCanvasProps {
|
|
10
|
+
samples: Sample[]
|
|
11
|
+
maxLabelLength: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function LabelsCanvas({
|
|
15
|
+
samples,
|
|
16
|
+
maxLabelLength,
|
|
17
|
+
}: LabelsCanvasProps) {
|
|
18
|
+
const theme = useTheme()
|
|
19
|
+
const canvasRef = useRef<HTMLCanvasElement>(null)
|
|
20
|
+
|
|
21
|
+
const labelWidth = maxLabelLength * CHAR_WIDTH + LABEL_PADDING
|
|
22
|
+
const canvasHeight = samples.length * ROW_HEIGHT
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const canvas = canvasRef.current
|
|
26
|
+
if (!canvas) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const ctx = canvas.getContext('2d')
|
|
31
|
+
if (!ctx) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const dpr = window.devicePixelRatio || 1
|
|
36
|
+
canvas.width = labelWidth * dpr
|
|
37
|
+
canvas.height = canvasHeight * dpr
|
|
38
|
+
canvas.style.width = `${labelWidth}px`
|
|
39
|
+
canvas.style.height = `${canvasHeight}px`
|
|
40
|
+
ctx.scale(dpr, dpr)
|
|
41
|
+
|
|
42
|
+
ctx.fillStyle = theme.palette.background.paper
|
|
43
|
+
ctx.fillRect(0, 0, labelWidth, canvasHeight)
|
|
44
|
+
|
|
45
|
+
ctx.font = FONT
|
|
46
|
+
ctx.textBaseline = 'top'
|
|
47
|
+
|
|
48
|
+
for (let rowIdx = 0; rowIdx < samples.length; rowIdx++) {
|
|
49
|
+
const sample = samples[rowIdx]!
|
|
50
|
+
const y = rowIdx * ROW_HEIGHT
|
|
51
|
+
|
|
52
|
+
ctx.fillStyle = theme.palette.text.secondary
|
|
53
|
+
ctx.fillText(sample.label ?? sample.id, 2, y + 2)
|
|
54
|
+
}
|
|
55
|
+
}, [samples, labelWidth, canvasHeight, theme])
|
|
56
|
+
|
|
57
|
+
return <canvas ref={canvasRef} style={{ display: 'block' }} />
|
|
58
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { getSession } from '@jbrowse/core/util'
|
|
4
|
+
import { colord } from '@jbrowse/core/util/colord'
|
|
5
|
+
import { observer } from 'mobx-react'
|
|
6
|
+
import { makeStyles } from 'tss-react/mui'
|
|
7
|
+
|
|
8
|
+
import type { MafSequenceWidgetModel } from './stateModelFactory'
|
|
9
|
+
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
10
|
+
|
|
11
|
+
const useStyles = makeStyles()(theme => ({
|
|
12
|
+
highlight: {
|
|
13
|
+
height: '100%',
|
|
14
|
+
position: 'absolute',
|
|
15
|
+
background: colord(theme.palette.primary.main).alpha(0.4).toRgbString(),
|
|
16
|
+
borderLeft: `2px solid ${theme.palette.primary.main}`,
|
|
17
|
+
borderRight: `2px solid ${theme.palette.primary.main}`,
|
|
18
|
+
pointerEvents: 'none',
|
|
19
|
+
zIndex: 10,
|
|
20
|
+
},
|
|
21
|
+
}))
|
|
22
|
+
|
|
23
|
+
const MafSequenceHoverHighlight = observer(function MafSequenceHoverHighlight({
|
|
24
|
+
model,
|
|
25
|
+
}: {
|
|
26
|
+
model: LinearGenomeViewModel
|
|
27
|
+
}) {
|
|
28
|
+
const { classes } = useStyles()
|
|
29
|
+
const session = getSession(model)
|
|
30
|
+
const { assemblyManager } = session
|
|
31
|
+
|
|
32
|
+
// Find MafSequenceWidget instances that are connected to this view
|
|
33
|
+
const widgets =
|
|
34
|
+
'widgets' in session ? (session.widgets as Map<string, unknown>) : undefined
|
|
35
|
+
if (!widgets) {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const highlights: React.ReactNode[] = []
|
|
40
|
+
|
|
41
|
+
for (const [, widget] of widgets) {
|
|
42
|
+
const w = widget as {
|
|
43
|
+
type?: string
|
|
44
|
+
connectedViewId?: string
|
|
45
|
+
hoverHighlight?: unknown
|
|
46
|
+
}
|
|
47
|
+
if (w.type === 'MafSequenceWidget' && w.connectedViewId === model.id) {
|
|
48
|
+
const mafWidget = widget as MafSequenceWidgetModel
|
|
49
|
+
const { hoverHighlight } = mafWidget
|
|
50
|
+
|
|
51
|
+
if (hoverHighlight) {
|
|
52
|
+
const { refName, start, end, assemblyName } = hoverHighlight
|
|
53
|
+
const assembly = assemblyManager.get(assemblyName)
|
|
54
|
+
const canonicalRefName =
|
|
55
|
+
assembly?.getCanonicalRefName(refName) ?? refName
|
|
56
|
+
|
|
57
|
+
const startPx = model.bpToPx({
|
|
58
|
+
refName: canonicalRefName,
|
|
59
|
+
coord: start,
|
|
60
|
+
})
|
|
61
|
+
const endPx = model.bpToPx({ refName: canonicalRefName, coord: end })
|
|
62
|
+
|
|
63
|
+
if (startPx && endPx) {
|
|
64
|
+
const left =
|
|
65
|
+
Math.min(startPx.offsetPx, endPx.offsetPx) - model.offsetPx
|
|
66
|
+
const width = Math.max(Math.abs(endPx.offsetPx - startPx.offsetPx), 3)
|
|
67
|
+
|
|
68
|
+
highlights.push(
|
|
69
|
+
<div
|
|
70
|
+
key={`maf-hover-${mafWidget.id}`}
|
|
71
|
+
className={classes.highlight}
|
|
72
|
+
style={{ left, width }}
|
|
73
|
+
/>,
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return <>{highlights}</>
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
export default MafSequenceHoverHighlight
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import MafSequenceHoverHighlight from './MafSequenceHoverHighlight'
|
|
4
|
+
|
|
5
|
+
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
6
|
+
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
7
|
+
|
|
8
|
+
export default function MafSequenceHoverHighlightExtensionF(
|
|
9
|
+
pluginManager: PluginManager,
|
|
10
|
+
) {
|
|
11
|
+
pluginManager.addToExtensionPoint(
|
|
12
|
+
'LinearGenomeView-TracksContainerComponent',
|
|
13
|
+
(rest: React.ReactNode[], props: Record<string, unknown>) => {
|
|
14
|
+
const model = props.model as LinearGenomeViewModel
|
|
15
|
+
return [
|
|
16
|
+
...rest,
|
|
17
|
+
<MafSequenceHoverHighlight
|
|
18
|
+
key="maf-sequence-hover-highlight"
|
|
19
|
+
model={model}
|
|
20
|
+
/>,
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
)
|
|
24
|
+
}
|