@apollo-annotation/jbrowse-plugin-apollo 0.3.8 → 0.3.9
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/dist/index.esm.js +10932 -10932
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +10845 -10846
- package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.development.js +18619 -21342
- package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
- package/package.json +7 -7
- package/src/ApolloInternetAccount/model.ts +81 -63
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +4 -4
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +9 -7
- package/src/BackendDrivers/CollaborationServerDriver.ts +49 -18
- package/src/BackendDrivers/DesktopFileDriver.ts +2 -2
- package/src/ChangeManager.ts +3 -1
- package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -4
- package/src/FeatureDetailsWidget/NumberTextField.tsx +5 -2
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +39 -203
- package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +92 -0
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +6 -102
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +31 -230
- package/src/LinearApolloDisplay/glyphs/util.ts +19 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +181 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceTrack.ts +218 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +62 -386
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +6 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +122 -70
- package/src/components/AddAssembly.tsx +33 -37
- package/src/components/AddFeature.tsx +21 -18
- package/src/components/AddRefSeqAliases.tsx +56 -42
- package/src/components/CopyFeature.tsx +1 -1
- package/src/components/CreateApolloAnnotation.tsx +22 -10
- package/src/components/DeleteAssembly.tsx +2 -9
- package/src/components/DownloadGFF3.tsx +2 -2
- package/src/components/ManageChecks.tsx +2 -9
- package/src/components/ManageUsers.tsx +23 -22
- package/src/components/OntologyTermAutocomplete.tsx +1 -8
- package/src/components/ViewChangeLog.tsx +25 -50
- package/src/components/ViewCheckResults.tsx +1 -7
- package/src/config.ts +3 -3
- package/src/index.ts +17 -16
- package/src/makeDisplayComponent.tsx +9 -13
- package/src/session/ClientDataStore.ts +32 -14
- package/src/session/session.ts +19 -27
- package/src/util/glyphUtils.ts +178 -1
- package/src/util/loadAssemblyIntoClient.ts +3 -2
|
@@ -1,153 +1,15 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
2
2
|
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
3
3
|
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
4
|
-
import {
|
|
5
|
-
type Frame,
|
|
6
|
-
defaultCodonTable,
|
|
7
|
-
getFrame,
|
|
8
|
-
revcom,
|
|
9
|
-
} from '@jbrowse/core/util'
|
|
10
4
|
import { type Theme, createTheme } from '@mui/material'
|
|
11
5
|
import { autorun } from 'mobx'
|
|
12
6
|
import { type Instance, addDisposer } from 'mobx-state-tree'
|
|
13
7
|
|
|
14
|
-
import {
|
|
8
|
+
import { drawSequenceOverlay } from '../drawSequenceOverlay'
|
|
9
|
+
import { drawSequenceTrack } from '../drawSequenceTrack'
|
|
15
10
|
|
|
16
11
|
import { baseModelFactory } from './base'
|
|
17
12
|
|
|
18
|
-
function colorCode(letter: string, theme: Theme) {
|
|
19
|
-
return (
|
|
20
|
-
theme.palette.bases[
|
|
21
|
-
letter.toUpperCase() as keyof Theme['palette']['bases']
|
|
22
|
-
].main.toString() ?? 'lightgray'
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function codonColorCode(letter: string, highContrast?: boolean) {
|
|
27
|
-
const colorMap: Record<string, string | undefined> = {
|
|
28
|
-
M: '#33ee33',
|
|
29
|
-
'*': highContrast ? '#000000' : '#f44336',
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return colorMap[letter.toUpperCase()]
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function reverseCodonSeq(seq: string): string {
|
|
36
|
-
// disable because sequence is all ascii
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-spread
|
|
38
|
-
return [...seq]
|
|
39
|
-
.map((c) => revcom(c))
|
|
40
|
-
.reverse()
|
|
41
|
-
.join('')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function drawLetter(
|
|
45
|
-
seqTrackctx: CanvasRenderingContext2D,
|
|
46
|
-
startPx: number,
|
|
47
|
-
widthPx: number,
|
|
48
|
-
letter: string,
|
|
49
|
-
textY: number,
|
|
50
|
-
) {
|
|
51
|
-
const fontSize = Math.min(widthPx, 10)
|
|
52
|
-
seqTrackctx.fillStyle = '#000'
|
|
53
|
-
seqTrackctx.font = `${fontSize}px`
|
|
54
|
-
const textWidth = seqTrackctx.measureText(letter).width
|
|
55
|
-
const textX = startPx + (widthPx - textWidth) / 2
|
|
56
|
-
seqTrackctx.fillText(letter, textX, textY + 10)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function drawTranslation(
|
|
60
|
-
seqTrackctx: CanvasRenderingContext2D,
|
|
61
|
-
bpPerPx: number,
|
|
62
|
-
trnslStartPx: number,
|
|
63
|
-
trnslY: number,
|
|
64
|
-
trnslWidthPx: number,
|
|
65
|
-
sequenceRowHeight: number,
|
|
66
|
-
seq: string,
|
|
67
|
-
i: number,
|
|
68
|
-
reverse: boolean,
|
|
69
|
-
showStartCodons: boolean,
|
|
70
|
-
showStopCodons: boolean,
|
|
71
|
-
highContrast: boolean,
|
|
72
|
-
) {
|
|
73
|
-
let codonSeq: string = seq.slice(i, i + 3).toUpperCase()
|
|
74
|
-
if (reverse) {
|
|
75
|
-
codonSeq = reverseCodonSeq(codonSeq)
|
|
76
|
-
}
|
|
77
|
-
const codonLetter =
|
|
78
|
-
defaultCodonTable[codonSeq as keyof typeof defaultCodonTable]
|
|
79
|
-
if (!codonLetter) {
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
const fillColor = codonColorCode(codonLetter, highContrast)
|
|
83
|
-
if (
|
|
84
|
-
fillColor &&
|
|
85
|
-
((showStopCodons && codonLetter == '*') ||
|
|
86
|
-
(showStartCodons && codonLetter != '*'))
|
|
87
|
-
) {
|
|
88
|
-
seqTrackctx.fillStyle = fillColor
|
|
89
|
-
seqTrackctx.fillRect(trnslStartPx, trnslY, trnslWidthPx, sequenceRowHeight)
|
|
90
|
-
}
|
|
91
|
-
if (bpPerPx <= 0.1) {
|
|
92
|
-
seqTrackctx.rect(trnslStartPx, trnslY, trnslWidthPx, sequenceRowHeight)
|
|
93
|
-
seqTrackctx.stroke()
|
|
94
|
-
drawLetter(seqTrackctx, trnslStartPx, trnslWidthPx, codonLetter, trnslY)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function getTranslationRow(frame: Frame, bpPerPx: number) {
|
|
99
|
-
const offset = bpPerPx <= 1 ? 2 : 0
|
|
100
|
-
switch (frame) {
|
|
101
|
-
case 3: {
|
|
102
|
-
return 0
|
|
103
|
-
}
|
|
104
|
-
case 2: {
|
|
105
|
-
return 1
|
|
106
|
-
}
|
|
107
|
-
case 1: {
|
|
108
|
-
return 2
|
|
109
|
-
}
|
|
110
|
-
case -1: {
|
|
111
|
-
return 3 + offset
|
|
112
|
-
}
|
|
113
|
-
case -2: {
|
|
114
|
-
return 4 + offset
|
|
115
|
-
}
|
|
116
|
-
case -3: {
|
|
117
|
-
return 5 + offset
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function getSeqRow(
|
|
123
|
-
strand: 1 | -1 | undefined,
|
|
124
|
-
bpPerPx: number,
|
|
125
|
-
): number | undefined {
|
|
126
|
-
if (bpPerPx > 1 || strand === undefined) {
|
|
127
|
-
return
|
|
128
|
-
}
|
|
129
|
-
return strand === 1 ? 3 : 4
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function highlightSeq(
|
|
133
|
-
seqTrackOverlayctx: CanvasRenderingContext2D,
|
|
134
|
-
theme: Theme,
|
|
135
|
-
startPx: number,
|
|
136
|
-
sequenceRowHeight: number,
|
|
137
|
-
row: number | undefined,
|
|
138
|
-
widthPx: number,
|
|
139
|
-
) {
|
|
140
|
-
if (row !== undefined) {
|
|
141
|
-
seqTrackOverlayctx.fillStyle = theme.palette.action.focus
|
|
142
|
-
seqTrackOverlayctx.fillRect(
|
|
143
|
-
startPx,
|
|
144
|
-
sequenceRowHeight * row,
|
|
145
|
-
widthPx,
|
|
146
|
-
sequenceRowHeight,
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
13
|
export function renderingModelFactory(
|
|
152
14
|
pluginManager: PluginManager,
|
|
153
15
|
configSchema: AnyConfigurationSchemaType,
|
|
@@ -180,181 +42,45 @@ export function renderingModelFactory(
|
|
|
180
42
|
self,
|
|
181
43
|
autorun(
|
|
182
44
|
() => {
|
|
183
|
-
const {
|
|
184
|
-
|
|
45
|
+
const {
|
|
46
|
+
lgv,
|
|
47
|
+
seqTrackCanvas,
|
|
48
|
+
theme,
|
|
49
|
+
highContrast,
|
|
50
|
+
showStartCodons,
|
|
51
|
+
showStopCodons,
|
|
52
|
+
sequenceRowHeight,
|
|
53
|
+
session,
|
|
54
|
+
} = self
|
|
55
|
+
if (
|
|
56
|
+
!lgv.initialized ||
|
|
57
|
+
self.regionCannotBeRendered() ||
|
|
58
|
+
!seqTrackCanvas
|
|
59
|
+
) {
|
|
185
60
|
return
|
|
186
61
|
}
|
|
187
|
-
|
|
62
|
+
|
|
63
|
+
const trnslWidthPx = 3 / lgv.bpPerPx
|
|
188
64
|
if (trnslWidthPx < 1) {
|
|
189
65
|
return
|
|
190
66
|
}
|
|
191
|
-
const seqTrackctx = self.seqTrackCanvas?.getContext('2d')
|
|
192
|
-
if (!seqTrackctx) {
|
|
193
|
-
return
|
|
194
|
-
}
|
|
195
67
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
68
|
+
const { bpPerPx, offsetPx, dynamicBlocks } = lgv
|
|
69
|
+
// we have to be really explicit about passing in individual
|
|
70
|
+
// variables here and not just e.g. "lgv" so that the autorun
|
|
71
|
+
// tracks the variables correctly
|
|
72
|
+
drawSequenceTrack(
|
|
73
|
+
seqTrackCanvas,
|
|
74
|
+
theme,
|
|
75
|
+
bpPerPx,
|
|
76
|
+
offsetPx,
|
|
77
|
+
dynamicBlocks,
|
|
78
|
+
highContrast,
|
|
79
|
+
showStartCodons,
|
|
80
|
+
showStopCodons,
|
|
81
|
+
sequenceRowHeight,
|
|
82
|
+
session,
|
|
201
83
|
)
|
|
202
|
-
const frames =
|
|
203
|
-
self.lgv.bpPerPx <= 1
|
|
204
|
-
? [3, 2, 1, 0, 0, -1, -2, -3]
|
|
205
|
-
: [3, 2, 1, -1, -2, -3]
|
|
206
|
-
let height = 0
|
|
207
|
-
if (theme) {
|
|
208
|
-
for (const frame of frames) {
|
|
209
|
-
let frameColor = theme.palette.framesCDS.at(frame)?.main
|
|
210
|
-
if (frameColor) {
|
|
211
|
-
let offsetPx = 0
|
|
212
|
-
if (self.highContrast) {
|
|
213
|
-
frameColor = 'white'
|
|
214
|
-
offsetPx = 1
|
|
215
|
-
// eslint-disable-next-line prefer-destructuring
|
|
216
|
-
seqTrackctx.fillStyle = theme.palette.grey[200]
|
|
217
|
-
seqTrackctx.fillRect(
|
|
218
|
-
0,
|
|
219
|
-
height,
|
|
220
|
-
self.lgv.dynamicBlocks.totalWidthPx,
|
|
221
|
-
self.sequenceRowHeight,
|
|
222
|
-
)
|
|
223
|
-
}
|
|
224
|
-
seqTrackctx.fillStyle = frameColor
|
|
225
|
-
seqTrackctx.fillRect(
|
|
226
|
-
0 + offsetPx,
|
|
227
|
-
height + offsetPx,
|
|
228
|
-
self.lgv.dynamicBlocks.totalWidthPx - 2 * offsetPx,
|
|
229
|
-
self.sequenceRowHeight - 2 * offsetPx,
|
|
230
|
-
)
|
|
231
|
-
}
|
|
232
|
-
height += self.sequenceRowHeight
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
for (const [idx, region] of self.regions.entries()) {
|
|
237
|
-
const { apolloDataStore } =
|
|
238
|
-
self.session as unknown as ApolloSessionModel
|
|
239
|
-
const assembly = apolloDataStore.assemblies.get(
|
|
240
|
-
region.assemblyName,
|
|
241
|
-
)
|
|
242
|
-
const ref = assembly?.getByRefName(region.refName)
|
|
243
|
-
const seq = ref?.getSequence(region.start, region.end)
|
|
244
|
-
if (!seq) {
|
|
245
|
-
return
|
|
246
|
-
}
|
|
247
|
-
// disable because sequence is all ascii
|
|
248
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-spread
|
|
249
|
-
for (const [i, letter] of [...seq].entries()) {
|
|
250
|
-
const trnslXOffset =
|
|
251
|
-
(self.lgv.bpToPx({
|
|
252
|
-
refName: region.refName,
|
|
253
|
-
coord: region.start + i,
|
|
254
|
-
regionNumber: idx,
|
|
255
|
-
})?.offsetPx ?? 0) - self.lgv.offsetPx
|
|
256
|
-
const trnslStartPx = self.lgv.displayedRegions[idx].reversed
|
|
257
|
-
? trnslXOffset - trnslWidthPx
|
|
258
|
-
: trnslXOffset
|
|
259
|
-
|
|
260
|
-
// Draw translation forward
|
|
261
|
-
for (let j = 2; j >= 0; j--) {
|
|
262
|
-
if ((region.start + i) % 3 === j) {
|
|
263
|
-
drawTranslation(
|
|
264
|
-
seqTrackctx,
|
|
265
|
-
self.lgv.bpPerPx,
|
|
266
|
-
trnslStartPx,
|
|
267
|
-
self.sequenceRowHeight * (2 - j),
|
|
268
|
-
trnslWidthPx,
|
|
269
|
-
self.sequenceRowHeight,
|
|
270
|
-
seq,
|
|
271
|
-
i,
|
|
272
|
-
false,
|
|
273
|
-
self.showStartCodons,
|
|
274
|
-
self.showStopCodons,
|
|
275
|
-
self.highContrast,
|
|
276
|
-
)
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (self.lgv.bpPerPx <= 1) {
|
|
281
|
-
const xOffset =
|
|
282
|
-
(self.lgv.bpToPx({
|
|
283
|
-
refName: region.refName,
|
|
284
|
-
coord: region.start + i,
|
|
285
|
-
regionNumber: idx,
|
|
286
|
-
})?.offsetPx ?? 0) - self.lgv.offsetPx
|
|
287
|
-
const widthPx = 1 / self.lgv.bpPerPx
|
|
288
|
-
const startPx = self.lgv.displayedRegions[idx].reversed
|
|
289
|
-
? xOffset - widthPx
|
|
290
|
-
: xOffset
|
|
291
|
-
|
|
292
|
-
// Draw forward
|
|
293
|
-
seqTrackctx.beginPath()
|
|
294
|
-
seqTrackctx.fillStyle = colorCode(letter, self.theme)
|
|
295
|
-
seqTrackctx.rect(
|
|
296
|
-
startPx,
|
|
297
|
-
self.sequenceRowHeight * 3,
|
|
298
|
-
widthPx,
|
|
299
|
-
self.sequenceRowHeight,
|
|
300
|
-
)
|
|
301
|
-
seqTrackctx.fill()
|
|
302
|
-
if (self.lgv.bpPerPx <= 0.1) {
|
|
303
|
-
seqTrackctx.stroke()
|
|
304
|
-
drawLetter(
|
|
305
|
-
seqTrackctx,
|
|
306
|
-
startPx,
|
|
307
|
-
widthPx,
|
|
308
|
-
letter,
|
|
309
|
-
self.sequenceRowHeight * 3,
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Draw reverse
|
|
314
|
-
const revLetter = revcom(letter)
|
|
315
|
-
seqTrackctx.beginPath()
|
|
316
|
-
seqTrackctx.fillStyle = colorCode(revLetter, self.theme)
|
|
317
|
-
seqTrackctx.rect(
|
|
318
|
-
startPx,
|
|
319
|
-
self.sequenceRowHeight * 4,
|
|
320
|
-
widthPx,
|
|
321
|
-
self.sequenceRowHeight,
|
|
322
|
-
)
|
|
323
|
-
seqTrackctx.fill()
|
|
324
|
-
if (self.lgv.bpPerPx <= 0.1) {
|
|
325
|
-
seqTrackctx.stroke()
|
|
326
|
-
drawLetter(
|
|
327
|
-
seqTrackctx,
|
|
328
|
-
startPx,
|
|
329
|
-
widthPx,
|
|
330
|
-
revLetter,
|
|
331
|
-
self.sequenceRowHeight * 4,
|
|
332
|
-
)
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// Draw translation reverse
|
|
337
|
-
for (let k = 0; k <= 2; k++) {
|
|
338
|
-
const rowOffset = self.lgv.bpPerPx <= 1 ? 5 : 3
|
|
339
|
-
if ((region.start + i) % 3 === k) {
|
|
340
|
-
drawTranslation(
|
|
341
|
-
seqTrackctx,
|
|
342
|
-
self.lgv.bpPerPx,
|
|
343
|
-
trnslStartPx,
|
|
344
|
-
self.sequenceRowHeight * (rowOffset + k),
|
|
345
|
-
trnslWidthPx,
|
|
346
|
-
self.sequenceRowHeight,
|
|
347
|
-
seq,
|
|
348
|
-
i,
|
|
349
|
-
true,
|
|
350
|
-
self.showStartCodons,
|
|
351
|
-
self.showStopCodons,
|
|
352
|
-
self.highContrast,
|
|
353
|
-
)
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
84
|
},
|
|
359
85
|
{ name: 'LinearApolloReferenceSequenceDisplayRenderSequence' },
|
|
360
86
|
),
|
|
@@ -363,11 +89,15 @@ export function renderingModelFactory(
|
|
|
363
89
|
self,
|
|
364
90
|
autorun(
|
|
365
91
|
() => {
|
|
366
|
-
|
|
92
|
+
const { seqTrackOverlayCanvas } = self
|
|
93
|
+
if (
|
|
94
|
+
!self.lgv.initialized ||
|
|
95
|
+
self.regionCannotBeRendered() ||
|
|
96
|
+
!seqTrackOverlayCanvas
|
|
97
|
+
) {
|
|
367
98
|
return
|
|
368
99
|
}
|
|
369
|
-
const seqTrackOverlayctx =
|
|
370
|
-
self.seqTrackOverlayCanvas?.getContext('2d')
|
|
100
|
+
const seqTrackOverlayctx = seqTrackOverlayCanvas.getContext('2d')
|
|
371
101
|
if (!seqTrackOverlayctx) {
|
|
372
102
|
return
|
|
373
103
|
}
|
|
@@ -381,90 +111,36 @@ export function renderingModelFactory(
|
|
|
381
111
|
|
|
382
112
|
const {
|
|
383
113
|
hoveredFeature,
|
|
114
|
+
selectedFeature,
|
|
384
115
|
lgv,
|
|
385
|
-
regions,
|
|
386
116
|
sequenceRowHeight,
|
|
387
117
|
session,
|
|
388
118
|
theme,
|
|
389
119
|
} = self
|
|
390
120
|
|
|
391
|
-
if (!hoveredFeature) {
|
|
121
|
+
if (!(hoveredFeature || selectedFeature)) {
|
|
392
122
|
return
|
|
393
123
|
}
|
|
394
|
-
const {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
continue
|
|
414
|
-
}
|
|
415
|
-
for (const dl of cdsLocs) {
|
|
416
|
-
const frame = getFrame(
|
|
417
|
-
dl.min,
|
|
418
|
-
dl.max,
|
|
419
|
-
feature.strand ?? 1,
|
|
420
|
-
dl.phase,
|
|
421
|
-
)
|
|
422
|
-
const row = getTranslationRow(frame, lgv.bpPerPx)
|
|
423
|
-
const offset =
|
|
424
|
-
(lgv.bpToPx({
|
|
425
|
-
refName: region.refName,
|
|
426
|
-
coord: dl.min,
|
|
427
|
-
regionNumber: idx,
|
|
428
|
-
})?.offsetPx ?? 0) - lgv.offsetPx
|
|
429
|
-
const widthPx = (dl.max - dl.min) / lgv.bpPerPx
|
|
430
|
-
const startPx = lgv.displayedRegions[idx].reversed
|
|
431
|
-
? offset - widthPx
|
|
432
|
-
: offset
|
|
433
|
-
|
|
434
|
-
highlightSeq(
|
|
435
|
-
seqTrackOverlayctx,
|
|
436
|
-
theme,
|
|
437
|
-
startPx,
|
|
438
|
-
sequenceRowHeight,
|
|
439
|
-
row,
|
|
440
|
-
widthPx,
|
|
441
|
-
)
|
|
442
|
-
}
|
|
443
|
-
} else {
|
|
444
|
-
const row = getSeqRow(feature.strand, lgv.bpPerPx)
|
|
445
|
-
const offset =
|
|
446
|
-
(lgv.bpToPx({
|
|
447
|
-
refName: region.refName,
|
|
448
|
-
coord: feature.min,
|
|
449
|
-
regionNumber: idx,
|
|
450
|
-
})?.offsetPx ?? 0) - lgv.offsetPx
|
|
451
|
-
const widthPx = feature.length / lgv.bpPerPx
|
|
452
|
-
const startPx = lgv.displayedRegions[idx].reversed
|
|
453
|
-
? offset - widthPx
|
|
454
|
-
: offset
|
|
455
|
-
|
|
456
|
-
highlightSeq(
|
|
457
|
-
seqTrackOverlayctx,
|
|
458
|
-
theme,
|
|
459
|
-
startPx,
|
|
460
|
-
sequenceRowHeight,
|
|
461
|
-
row,
|
|
462
|
-
widthPx,
|
|
463
|
-
)
|
|
464
|
-
}
|
|
465
|
-
}
|
|
124
|
+
const { bpPerPx, dynamicBlocks, offsetPx } = lgv
|
|
125
|
+
// we have to be really explicit about passing in individual
|
|
126
|
+
// variables here and not just e.g. "lgv" so that the autorun
|
|
127
|
+
// tracks the variables correctly
|
|
128
|
+
drawSequenceOverlay(
|
|
129
|
+
seqTrackOverlayCanvas,
|
|
130
|
+
seqTrackOverlayctx,
|
|
131
|
+
hoveredFeature,
|
|
132
|
+
selectedFeature,
|
|
133
|
+
sequenceRowHeight,
|
|
134
|
+
theme,
|
|
135
|
+
session,
|
|
136
|
+
bpPerPx,
|
|
137
|
+
offsetPx,
|
|
138
|
+
dynamicBlocks,
|
|
139
|
+
)
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'LinearApolloReferenceSequenceDisplayRenderSequenceHighlight',
|
|
466
143
|
},
|
|
467
|
-
{ name: 'LinearApolloDisplayRenderSeqHighlight' },
|
|
468
144
|
),
|
|
469
145
|
)
|
|
470
146
|
},
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from '@jbrowse/core/util'
|
|
12
12
|
import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
13
13
|
import ErrorIcon from '@mui/icons-material/Error'
|
|
14
|
+
import LockIcon from '@mui/icons-material/Lock'
|
|
14
15
|
import { Alert, Avatar, Badge, Box, Tooltip, useTheme } from '@mui/material'
|
|
15
16
|
import { observer } from 'mobx-react'
|
|
16
17
|
import React, { useEffect, useState } from 'react'
|
|
@@ -88,6 +89,11 @@ export const LinearApolloSixFrameDisplay = observer(
|
|
|
88
89
|
}
|
|
89
90
|
}}
|
|
90
91
|
>
|
|
92
|
+
{session.isLocked ? (
|
|
93
|
+
<div className={classes.locked} data-testid="lock-icon">
|
|
94
|
+
<LockIcon />
|
|
95
|
+
</div>
|
|
96
|
+
) : null}
|
|
91
97
|
{message ? (
|
|
92
98
|
<Alert
|
|
93
99
|
severity="warning"
|