@apollo-annotation/jbrowse-plugin-apollo 0.1.18 → 0.1.20

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.
Files changed (85) hide show
  1. package/dist/index.esm.js +3189 -3575
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +3185 -3570
  4. package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
  5. package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
  6. package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
  7. package/dist/jbrowse-plugin-apollo.umd.development.js +14884 -15905
  8. package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
  9. package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
  10. package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
  11. package/package.json +33 -33
  12. package/src/ApolloInternetAccount/addMenuItems.ts +18 -0
  13. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
  14. package/src/ApolloInternetAccount/configSchema.ts +5 -2
  15. package/src/ApolloInternetAccount/model.ts +14 -5
  16. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +94 -0
  17. package/src/ApolloRefNameAliasAdapter/configSchema.ts +12 -0
  18. package/src/ApolloRefNameAliasAdapter/index.ts +21 -0
  19. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +1 -0
  20. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +10 -10
  21. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +35 -32
  22. package/src/BackendDrivers/BackendDriver.ts +8 -0
  23. package/src/BackendDrivers/CollaborationServerDriver.ts +49 -1
  24. package/src/BackendDrivers/DesktopFileDriver.ts +14 -1
  25. package/src/BackendDrivers/InMemoryFileDriver.ts +17 -1
  26. package/src/ChangeManager.ts +1 -1
  27. package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +5 -25
  28. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +82 -0
  29. package/src/FeatureDetailsWidget/Attributes.tsx +11 -3
  30. package/src/FeatureDetailsWidget/BasicInformation.tsx +38 -30
  31. package/src/FeatureDetailsWidget/Sequence.tsx +7 -7
  32. package/src/FeatureDetailsWidget/TranscriptBasic.tsx +446 -0
  33. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +365 -0
  34. package/src/FeatureDetailsWidget/index.ts +2 -0
  35. package/src/FeatureDetailsWidget/model.ts +77 -9
  36. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +0 -2
  37. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +453 -380
  38. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +520 -0
  39. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +138 -134
  40. package/src/LinearApolloDisplay/glyphs/Glyph.ts +38 -370
  41. package/src/LinearApolloDisplay/glyphs/index.ts +1 -2
  42. package/src/LinearApolloDisplay/stateModel/base.ts +3 -6
  43. package/src/LinearApolloDisplay/stateModel/getGlyph.ts +30 -30
  44. package/src/LinearApolloDisplay/stateModel/index.ts +5 -1
  45. package/src/LinearApolloDisplay/stateModel/layouts.ts +32 -24
  46. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +206 -217
  47. package/src/LinearApolloDisplay/stateModel/rendering.ts +43 -67
  48. package/src/OntologyManager/OntologyStore/fulltext.ts +1 -1
  49. package/src/OntologyManager/OntologyStore/index.ts +2 -1
  50. package/src/OntologyManager/index.ts +6 -2
  51. package/src/OntologyManager/util.ts +2 -2
  52. package/src/SixFrameFeatureDisplay/stateModel.ts +15 -10
  53. package/src/TabularEditor/HybridGrid/ChangeHandling.ts +21 -46
  54. package/src/TabularEditor/HybridGrid/Feature.tsx +31 -82
  55. package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +3 -2
  56. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +2 -3
  57. package/src/TabularEditor/HybridGrid/NumberCell.tsx +1 -0
  58. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +46 -5
  59. package/src/TabularEditor/model.ts +5 -3
  60. package/src/components/AddAssembly.tsx +15 -9
  61. package/src/components/AddChildFeature.tsx +7 -73
  62. package/src/components/AddFeature.tsx +2 -57
  63. package/src/components/AddRefSeqAliases.tsx +285 -0
  64. package/src/components/CopyFeature.tsx +16 -33
  65. package/src/components/DeleteFeature.tsx +4 -6
  66. package/src/components/ImportFeatures.tsx +6 -3
  67. package/src/components/LogOut.tsx +105 -0
  68. package/src/components/ManageChecks.tsx +1 -0
  69. package/src/components/ManageUsers.tsx +21 -1
  70. package/src/components/ModifyFeatureAttribute.tsx +2 -2
  71. package/src/components/OntologyTermAutocomplete.tsx +0 -2
  72. package/src/components/OntologyTermMultiSelect.tsx +1 -0
  73. package/src/components/OpenLocalFile.tsx +6 -5
  74. package/src/components/ViewChangeLog.tsx +1 -0
  75. package/src/components/ViewCheckResults.tsx +1 -0
  76. package/src/components/index.ts +4 -0
  77. package/src/extensions/annotationFromPileup.ts +10 -16
  78. package/src/index.ts +57 -3
  79. package/src/session/ClientDataStore.ts +49 -46
  80. package/src/session/session.ts +186 -114
  81. package/src/util/loadAssemblyIntoClient.ts +4 -210
  82. package/src/FeatureDetailsWidget/RelatedFeature.tsx +0 -97
  83. package/src/LinearApolloDisplay/glyphs/CanonicalGeneGlyph.ts +0 -1204
  84. package/src/LinearApolloDisplay/glyphs/ImplicitExonGeneGlyph.ts +0 -716
  85. package/src/LinearApolloDisplay/stateModel/glyphs.ts +0 -47
@@ -1,405 +1,73 @@
1
- /* eslint-disable @typescript-eslint/unbound-method */
2
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
- /* eslint-disable @typescript-eslint/no-unsafe-return */
5
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
1
+ import { AnnotationFeature } from '@apollo-annotation/mst'
6
2
  import { MenuItem } from '@jbrowse/core/ui'
7
- import { AbstractSessionModel, SessionWithWidgets } from '@jbrowse/core/util'
8
- import { alpha } from '@mui/material'
9
3
 
10
- import {
11
- AddChildFeature,
12
- CopyFeature,
13
- DeleteFeature,
14
- ModifyFeatureAttribute,
15
- } from '../../components'
16
4
  import {
17
5
  LinearApolloDisplayMouseEvents,
18
- MousePosition,
6
+ MousePositionWithFeatureAndGlyph,
19
7
  } from '../stateModel/mouseEvents'
20
8
  import { LinearApolloDisplayRendering } from '../stateModel/rendering'
21
9
  import { CanvasMouseEvent } from '../types'
22
10
 
23
- export abstract class Glyph {
11
+ export interface Glyph {
24
12
  /** @returns number of layout rows used by this glyph with this feature and zoom level */
25
- abstract getRowCount(feature: AnnotationFeatureI, bpPerPx: number): number
26
-
13
+ getRowCount(feature: AnnotationFeature, bpPerPx: number): number
27
14
  /** draw the feature's primary rendering on the canvas */
28
- abstract draw(
29
- display: LinearApolloDisplayRendering,
15
+ draw(
30
16
  ctx: CanvasRenderingContext2D,
31
- feature: AnnotationFeatureI,
32
- xOffset: number,
17
+ feature: AnnotationFeature,
33
18
  row: number,
34
- reversed: boolean,
19
+ stateModel: LinearApolloDisplayRendering,
20
+ displayedRegionIndex: number,
35
21
  ): void
36
-
37
22
  /** @returns the feature or subfeature at the given bp and row number in this glyph's layout */
38
- abstract getFeatureFromLayout(
39
- feature: AnnotationFeatureI,
23
+ getFeatureFromLayout(
24
+ feature: AnnotationFeature,
40
25
  bp: number,
41
26
  row: number,
42
- ): AnnotationFeatureI | undefined
43
-
44
- abstract getRowForFeature(
45
- feature: AnnotationFeatureI,
46
- childFeature: AnnotationFeatureI,
27
+ ): AnnotationFeature | undefined
28
+ getRowForFeature(
29
+ feature: AnnotationFeature,
30
+ childFeature: AnnotationFeature,
47
31
  ): number | undefined
48
32
 
49
- abstract continueDrag(
50
- display: LinearApolloDisplayRendering,
51
- currentMousePosition: MousePosition,
52
- ): void
53
-
54
33
  drawHover(
55
- _display: LinearApolloDisplayMouseEvents,
56
- _overlayCtx: CanvasRenderingContext2D,
57
- _rowNum?: number,
58
- _xOffset?: number,
59
- _reversed?: boolean,
60
- ) {
61
- return
62
- }
34
+ display: LinearApolloDisplayMouseEvents,
35
+ overlayCtx: CanvasRenderingContext2D,
36
+ ): void
63
37
 
64
38
  drawDragPreview(
65
- _display: LinearApolloDisplayMouseEvents,
66
- _ctx: CanvasRenderingContext2D,
67
- ) {
68
- return
69
- }
70
-
71
- /** @returns true if the current drag that is starting is valid */
72
- startDrag(
73
- _display: LinearApolloDisplayMouseEvents,
74
- _event: CanvasMouseEvent,
75
- ): boolean {
76
- return false
77
- }
78
-
79
- executeDrag(
80
- _display: LinearApolloDisplayMouseEvents,
81
- _event: CanvasMouseEvent,
82
- ): void {
83
- return
84
- }
39
+ display: LinearApolloDisplayMouseEvents,
40
+ ctx: CanvasRenderingContext2D,
41
+ ): void
85
42
 
86
43
  onMouseDown(
87
- _display: LinearApolloDisplayMouseEvents,
88
- _event: CanvasMouseEvent,
89
- ): void {
90
- return
91
- }
44
+ display: LinearApolloDisplayMouseEvents,
45
+ currentMousePosition: MousePositionWithFeatureAndGlyph,
46
+ event: CanvasMouseEvent,
47
+ ): void
92
48
 
93
49
  onMouseMove(
94
- _display: LinearApolloDisplayMouseEvents,
95
- _event: CanvasMouseEvent,
96
- ): void {
97
- return
98
- }
50
+ display: LinearApolloDisplayMouseEvents,
51
+ currentMousePosition: MousePositionWithFeatureAndGlyph,
52
+ event: CanvasMouseEvent,
53
+ ): void
99
54
 
100
55
  onMouseLeave(
101
- _display: LinearApolloDisplayMouseEvents,
102
- _event: CanvasMouseEvent,
103
- ): void {
104
- return
105
- }
56
+ display: LinearApolloDisplayMouseEvents,
57
+ currentMousePosition: MousePositionWithFeatureAndGlyph,
58
+ event: CanvasMouseEvent,
59
+ ): void
106
60
 
107
61
  onMouseUp(
108
- _display: LinearApolloDisplayMouseEvents,
109
- _event: CanvasMouseEvent,
110
- ): void {
111
- return
112
- }
113
-
114
- onContextMenu(
115
- _display: LinearApolloDisplayMouseEvents,
116
- _event: CanvasMouseEvent,
117
- ): void {
118
- return
119
- }
62
+ display: LinearApolloDisplayMouseEvents,
63
+ currentMousePosition: MousePositionWithFeatureAndGlyph,
64
+ event: CanvasMouseEvent,
65
+ ): void
120
66
 
121
67
  drawTooltip(
122
68
  display: LinearApolloDisplayMouseEvents,
123
69
  context: CanvasRenderingContext2D,
124
- ): void {
125
- const { apolloHover, apolloRowHeight, displayedRegions, lgv, theme } =
126
- display
127
- if (!apolloHover) {
128
- return
129
- }
130
- const { feature, mousePosition } = apolloHover
131
- if (!(feature && mousePosition)) {
132
- return
133
- }
134
- const { regionNumber, y } = mousePosition
135
- const displayedRegion = displayedRegions[regionNumber]
136
- const { refName, reversed } = displayedRegion
137
- const { bpPerPx, bpToPx, offsetPx } = lgv
138
-
139
- const { discontinuousLocations } = feature
140
- let start: number, end: number, length: number
141
- let location = 'Loc: '
142
- if (discontinuousLocations && discontinuousLocations.length > 0) {
143
- const lastLoc = discontinuousLocations.at(-1)
144
- if (!lastLoc) {
145
- return
146
- }
147
- ;({ start } = lastLoc)
148
- ;({ end } = lastLoc)
149
- length = lastLoc.end - lastLoc.start
150
-
151
- if (discontinuousLocations.length <= 2) {
152
- for (const [i, loc] of discontinuousLocations.entries()) {
153
- location += `${loc.start + 1}–${loc.end}`
154
- if (i !== discontinuousLocations.length - 1) {
155
- location += ','
156
- }
157
- }
158
- } else {
159
- const [firstLoc] = discontinuousLocations
160
- location += `${firstLoc.start + 1}–${firstLoc.end},…,${
161
- lastLoc.start + 1
162
- }–${lastLoc.end}`
163
- }
164
- } else {
165
- ;({ end, length, start } = feature)
166
- location += `${start + 1}–${end}`
167
- }
168
-
169
- let startPx =
170
- (bpToPx({ refName, coord: reversed ? end : start, regionNumber })
171
- ?.offsetPx ?? 0) - offsetPx
172
- const row = Math.floor(y / apolloRowHeight)
173
- const top = row * apolloRowHeight
174
- const widthPx = length / bpPerPx
175
-
176
- const featureType = `Type: ${feature.type}`
177
- const { attributes } = feature
178
- const featureName = attributes.get('gff_name')?.find((name) => name !== '')
179
- const textWidth = [
180
- context.measureText(featureType).width,
181
- context.measureText(location).width,
182
- ]
183
- if (featureName) {
184
- textWidth.push(context.measureText(`Name: ${featureName}`).width)
185
- }
186
- const maxWidth = Math.max(...textWidth)
187
-
188
- startPx = startPx + widthPx + 5
189
- context.fillStyle = alpha(
190
- theme?.palette.text.primary ?? 'rgb(1, 1, 1)',
191
- 0.7,
192
- )
193
- context.fillRect(
194
- startPx,
195
- top,
196
- maxWidth + 4,
197
- textWidth.length === 3 ? 45 : 35,
198
- )
199
- context.beginPath()
200
- context.moveTo(startPx, top)
201
- context.lineTo(startPx - 5, top + 5)
202
- context.lineTo(startPx, top + 10)
203
- context.fill()
204
- context.fillStyle =
205
- theme?.palette.background.default ?? 'rgba(255, 255, 255)'
206
- let textTop = top + 12
207
- context.fillText(featureType, startPx + 2, textTop)
208
- if (featureName) {
209
- textTop = textTop + 12
210
- context.fillText(`Name: ${featureName}`, startPx + 2, textTop)
211
- }
212
- textTop = textTop + 12
213
- context.fillText(location, startPx + 2, textTop)
214
- }
215
-
216
- getAdjacentFeatures(
217
- feature?: AnnotationFeatureI,
218
- parentFeature?: AnnotationFeatureI,
219
- ): {
220
- prevFeature?: AnnotationFeatureI
221
- nextFeature?: AnnotationFeatureI
222
- } {
223
- let prevFeature: AnnotationFeatureI | undefined
224
- let nextFeature: AnnotationFeatureI | undefined
225
- let i = 0
226
- if (!feature || !(parentFeature && parentFeature.children)) {
227
- return { prevFeature, nextFeature }
228
- }
229
- for (const [, f] of parentFeature.children) {
230
- if (f._id === feature._id) {
231
- break
232
- }
233
- i++
234
- }
235
- const keys = [...parentFeature.children.keys()]
236
- if (i > 0) {
237
- const key = keys[i - 1]
238
- prevFeature = parentFeature.children.get(key)
239
- }
240
- if (i < keys.length - 1) {
241
- const key = keys[i + 1]
242
- nextFeature = parentFeature.children.get(key)
243
- }
244
- return { prevFeature, nextFeature }
245
- }
246
-
247
- getParentFeature(
248
- feature?: AnnotationFeatureI,
249
- topLevelFeature?: AnnotationFeatureI,
250
- ) {
251
- let parentFeature
252
-
253
- if (!feature || !(topLevelFeature && topLevelFeature.children)) {
254
- return parentFeature
255
- }
256
-
257
- for (const [, f] of topLevelFeature.children) {
258
- if (f._id === feature._id) {
259
- parentFeature = topLevelFeature
260
- break
261
- }
262
- if (!f?.children) {
263
- continue
264
- }
265
- for (const [, cf] of f.children) {
266
- if (cf._id === feature._id) {
267
- parentFeature = f
268
- break
269
- }
270
- }
271
- if (parentFeature) {
272
- break
273
- }
274
- }
275
- return parentFeature
276
- }
70
+ ): void
277
71
 
278
- getContextMenuItems(display: LinearApolloDisplayMouseEvents): MenuItem[] {
279
- const {
280
- apolloHover,
281
- apolloInternetAccount: internetAccount,
282
- changeManager,
283
- getAssemblyId,
284
- regions,
285
- selectedFeature,
286
- session,
287
- setSelectedFeature,
288
- } = display
289
- const { feature: sourceFeature } = apolloHover ?? {}
290
- const role = internetAccount ? internetAccount.role : 'admin'
291
- const admin = role === 'admin'
292
- const readOnly = !(role && ['admin', 'user'].includes(role))
293
- const menuItems: MenuItem[] = []
294
- if (sourceFeature) {
295
- const [region] = regions
296
- const sourceAssemblyId = getAssemblyId(region.assemblyName)
297
- const currentAssemblyId = getAssemblyId(region.assemblyName)
298
- menuItems.push(
299
- {
300
- label: 'Add child feature',
301
- disabled: readOnly,
302
- onClick: () => {
303
- ;(session as unknown as AbstractSessionModel).queueDialog(
304
- (doneCallback) => [
305
- AddChildFeature,
306
- {
307
- session,
308
- handleClose: () => {
309
- doneCallback()
310
- },
311
- changeManager,
312
- sourceFeature,
313
- sourceAssemblyId,
314
- internetAccount,
315
- },
316
- ],
317
- )
318
- },
319
- },
320
- {
321
- label: 'Copy features and annotations',
322
- disabled: readOnly,
323
- onClick: () => {
324
- ;(session as unknown as AbstractSessionModel).queueDialog(
325
- (doneCallback) => [
326
- CopyFeature,
327
- {
328
- session,
329
- handleClose: () => {
330
- doneCallback()
331
- },
332
- changeManager,
333
- sourceFeature,
334
- sourceAssemblyId: currentAssemblyId,
335
- },
336
- ],
337
- )
338
- },
339
- },
340
- {
341
- label: 'Delete feature',
342
- disabled: !admin,
343
- onClick: () => {
344
- ;(session as unknown as AbstractSessionModel).queueDialog(
345
- (doneCallback) => [
346
- DeleteFeature,
347
- {
348
- session,
349
- handleClose: () => {
350
- doneCallback()
351
- },
352
- changeManager,
353
- sourceFeature,
354
- sourceAssemblyId: currentAssemblyId,
355
- selectedFeature,
356
- setSelectedFeature,
357
- },
358
- ],
359
- )
360
- },
361
- },
362
- {
363
- label: 'Modify feature attribute',
364
- disabled: readOnly,
365
- onClick: () => {
366
- ;(session as unknown as AbstractSessionModel).queueDialog(
367
- (doneCallback) => [
368
- ModifyFeatureAttribute,
369
- {
370
- session,
371
- handleClose: () => {
372
- doneCallback()
373
- },
374
- changeManager,
375
- sourceFeature,
376
- sourceAssemblyId: currentAssemblyId,
377
- },
378
- ],
379
- )
380
- },
381
- },
382
- {
383
- label: 'Edit feature details',
384
- onClick: () => {
385
- const apolloFeatureWidget = (
386
- session as unknown as SessionWithWidgets
387
- ).addWidget(
388
- 'ApolloFeatureDetailsWidget',
389
- 'apolloFeatureDetailsWidget',
390
- {
391
- feature: sourceFeature,
392
- assembly: currentAssemblyId,
393
- refName: region.refName,
394
- },
395
- )
396
- ;(session as unknown as SessionWithWidgets).showWidget(
397
- apolloFeatureWidget,
398
- )
399
- },
400
- },
401
- )
402
- }
403
- return menuItems
404
- }
72
+ getContextMenuItems(display: LinearApolloDisplayMouseEvents): MenuItem[]
405
73
  }
@@ -1,4 +1,3 @@
1
1
  export * from './BoxGlyph'
2
- export * from './CanonicalGeneGlyph'
2
+ export * from './GeneGlyph'
3
3
  export * from './GenericChildGlyph'
4
- export * from './ImplicitExonGeneGlyph'
@@ -3,7 +3,7 @@
3
3
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
4
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
5
5
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
6
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
6
+ import { AnnotationFeature } from '@apollo-annotation/mst'
7
7
  import { ConfigurationReference, getConf } from '@jbrowse/core/configuration'
8
8
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
9
9
  import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes'
@@ -75,9 +75,6 @@ export function baseModelFactory(
75
75
  )
76
76
  return regions
77
77
  },
78
- get displayedRegions() {
79
- return self.lgv.displayedRegions
80
- },
81
78
  regionCannotBeRendered(/* region */) {
82
79
  if (self.lgv && self.lgv.bpPerPx >= 200) {
83
80
  return 'Zoom in to see annotations'
@@ -117,13 +114,13 @@ export function baseModelFactory(
117
114
  }
118
115
  return assembly.name
119
116
  },
120
- get selectedFeature(): AnnotationFeatureI | undefined {
117
+ get selectedFeature(): AnnotationFeature | undefined {
121
118
  return (self.session as unknown as ApolloSessionModel)
122
119
  .apolloSelectedFeature
123
120
  },
124
121
  }))
125
122
  .actions((self) => ({
126
- setSelectedFeature(feature?: AnnotationFeatureI) {
123
+ setSelectedFeature(feature?: AnnotationFeature) {
127
124
  ;(
128
125
  self.session as unknown as ApolloSessionModel
129
126
  ).apolloSetSelectedFeature(feature)
@@ -1,40 +1,40 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
2
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
1
+ import { AnnotationFeature } from '@apollo-annotation/mst'
3
2
 
4
- import {
5
- BoxGlyph,
6
- CanonicalGeneGlyph,
7
- GenericChildGlyph,
8
- ImplicitExonGeneGlyph,
9
- } from '../glyphs'
3
+ import { boxGlyph, geneGlyph, genericChildGlyph } from '../glyphs'
10
4
  import { Glyph } from '../glyphs/Glyph'
11
5
 
12
- const boxGlyph = new BoxGlyph()
13
- const canonicalGeneGlyph = new CanonicalGeneGlyph()
14
- const genericChildGlyph = new GenericChildGlyph()
15
- const implicitExonGeneGlyph = new ImplicitExonGeneGlyph()
16
-
17
6
  /** get the appropriate glyph for the given top-level feature */
18
- export function getGlyph(feature: AnnotationFeatureI, _bpPerPx: number): Glyph {
19
- if (feature.type === 'gene') {
20
- let hasExon = false
21
- for (const [, mrna] of feature.children ?? new Map()) {
22
- if (mrna.type !== 'mRNA') {
23
- continue
24
- }
25
- for (const [, possibleExon] of mrna.children ?? new Map()) {
26
- if (possibleExon.type === 'exon') {
27
- hasExon = true
28
- }
29
- }
30
- }
31
- if (hasExon) {
32
- return canonicalGeneGlyph
33
- }
34
- return implicitExonGeneGlyph
7
+ export function getGlyph(feature: AnnotationFeature): Glyph {
8
+ if (looksLikeGene(feature)) {
9
+ return geneGlyph
35
10
  }
36
11
  if (feature.children?.size) {
37
12
  return genericChildGlyph
38
13
  }
39
14
  return boxGlyph
40
15
  }
16
+
17
+ function looksLikeGene(feature: AnnotationFeature) {
18
+ const { children } = feature
19
+ if (!children?.size) {
20
+ return false
21
+ }
22
+ for (const [, child] of children) {
23
+ if (child.type === 'mRNA') {
24
+ const { children: grandChildren } = child
25
+ if (!grandChildren?.size) {
26
+ return false
27
+ }
28
+ const hasCDS = [...grandChildren.values()].some(
29
+ (grandchild) => grandchild.type === 'CDS',
30
+ )
31
+ const hasExon = [...grandChildren.values()].some(
32
+ (grandchild) => grandchild.type === 'exon',
33
+ )
34
+ if (hasCDS && hasExon) {
35
+ return true
36
+ }
37
+ }
38
+ }
39
+ return false
40
+ }
@@ -17,4 +17,8 @@ export function stateModelFactory(
17
17
  }
18
18
 
19
19
  export type LinearApolloDisplayStateModel = ReturnType<typeof stateModelFactory>
20
- export type LinearApolloDisplay = Instance<LinearApolloDisplayStateModel>
20
+ // eslint disable because of
21
+ // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
22
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
23
+ export interface LinearApolloDisplay
24
+ extends Instance<LinearApolloDisplayStateModel> {}
@@ -1,7 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
2
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
4
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
2
+
3
+ import { AnnotationFeature } from '@apollo-annotation/mst'
5
4
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
6
5
  import PluginManager from '@jbrowse/core/PluginManager'
7
6
  import { AbstractSessionModel, doesIntersect2 } from '@jbrowse/core/util'
@@ -23,13 +22,13 @@ export function layoutsModelFactory(
23
22
  featuresMinMaxLimit: 500_000,
24
23
  })
25
24
  .volatile(() => ({
26
- seenFeatures: observable.map<string, AnnotationFeatureI>(),
25
+ seenFeatures: observable.map<string, AnnotationFeature>(),
27
26
  }))
28
27
  .views((self) => ({
29
28
  get featuresMinMax() {
30
29
  const { assemblyManager } =
31
30
  self.session as unknown as AbstractSessionModel
32
- return self.displayedRegions.map((region) => {
31
+ return self.lgv.displayedRegions.map((region) => {
33
32
  const assembly = assemblyManager.get(region.assemblyName)
34
33
  let min: number | undefined
35
34
  let max: number | undefined
@@ -48,10 +47,10 @@ export function layoutsModelFactory(
48
47
  if (max === undefined) {
49
48
  ;({ max } = feature)
50
49
  }
51
- if (feature.min < min) {
50
+ if (feature.minWithChildren < min) {
52
51
  ;({ min } = feature)
53
52
  }
54
- if (feature.end > max) {
53
+ if (feature.maxWithChildren > max) {
55
54
  ;({ max } = feature)
56
55
  }
57
56
  }
@@ -63,7 +62,7 @@ export function layoutsModelFactory(
63
62
  },
64
63
  }))
65
64
  .actions((self) => ({
66
- addSeenFeature(feature: AnnotationFeatureI) {
65
+ addSeenFeature(feature: AnnotationFeature) {
67
66
  self.seenFeatures.set(feature._id, feature)
68
67
  },
69
68
  deleteSeenFeature(featureId: string) {
@@ -74,12 +73,9 @@ export function layoutsModelFactory(
74
73
  get featureLayouts() {
75
74
  const { assemblyManager } =
76
75
  self.session as unknown as AbstractSessionModel
77
- return self.displayedRegions.map((region, idx) => {
76
+ return self.lgv.displayedRegions.map((region, idx) => {
78
77
  const assembly = assemblyManager.get(region.assemblyName)
79
- const featureLayout = new Map<
80
- number,
81
- [number, AnnotationFeatureI][]
82
- >()
78
+ const featureLayout = new Map<number, [number, AnnotationFeature][]>()
83
79
  const minMax = self.featuresMinMax[idx]
84
80
  if (!minMax) {
85
81
  return featureLayout
@@ -98,7 +94,7 @@ export function layoutsModelFactory(
98
94
  ) {
99
95
  continue
100
96
  }
101
- const rowCount = getGlyph(feature, self.lgv.bpPerPx).getRowCount(
97
+ const rowCount = getGlyph(feature).getRowCount(
102
98
  feature,
103
99
  self.lgv.bpPerPx,
104
100
  )
@@ -160,9 +156,9 @@ export function layoutsModelFactory(
160
156
  return featureLayout
161
157
  })
162
158
  },
163
- getFeatureLayoutPosition(feature: AnnotationFeatureI) {
159
+ getFeatureLayoutPosition(feature: AnnotationFeature) {
164
160
  const { featureLayouts } = this
165
- for (const layout of featureLayouts) {
161
+ for (const [idx, layout] of featureLayouts.entries()) {
166
162
  for (const [layoutRowNum, layoutRow] of layout) {
167
163
  for (const [featureRowNum, layoutFeature] of layoutRow) {
168
164
  if (featureRowNum !== 0) {
@@ -171,15 +167,23 @@ export function layoutsModelFactory(
171
167
  continue
172
168
  }
173
169
  if (feature._id === layoutFeature._id) {
174
- return { layoutRow: layoutRowNum, featureRow: featureRowNum }
170
+ return {
171
+ layoutIndex: idx,
172
+ layoutRow: layoutRowNum,
173
+ featureRow: featureRowNum,
174
+ }
175
175
  }
176
176
  if (layoutFeature.hasDescendant(feature._id)) {
177
- const row = getGlyph(
177
+ const row = getGlyph(layoutFeature).getRowForFeature(
178
178
  layoutFeature,
179
- self.lgv.bpPerPx,
180
- ).getRowForFeature(layoutFeature, feature)
179
+ feature,
180
+ )
181
181
  if (row !== undefined) {
182
- return { layoutRow: layoutRowNum, featureRow: row }
182
+ return {
183
+ layoutIndex: idx,
184
+ layoutRow: layoutRowNum,
185
+ featureRow: row,
186
+ }
183
187
  }
184
188
  }
185
189
  }
@@ -210,13 +214,17 @@ export function layoutsModelFactory(
210
214
  self.session as unknown as ApolloSessionModel
211
215
  ).apolloDataStore.assemblies.get(region.assemblyName)
212
216
  const ref = assembly?.getByRefName(region.refName)
213
- for (const [, feature] of ref?.features ?? new Map()) {
217
+ const features = ref?.features
218
+ if (!features) {
219
+ continue
220
+ }
221
+ for (const [, feature] of features) {
214
222
  if (
215
223
  doesIntersect2(
216
224
  region.start,
217
225
  region.end,
218
- feature.start,
219
- feature.end,
226
+ feature.min,
227
+ feature.max,
220
228
  ) &&
221
229
  !self.seenFeatures.has(feature._id)
222
230
  ) {