@apollo-annotation/jbrowse-plugin-apollo 0.3.6 → 0.3.8

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 (84) hide show
  1. package/dist/index.esm.js +4603 -2045
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +4611 -2039
  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 +9387 -4016
  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 +15 -15
  12. package/src/ApolloInternetAccount/model.ts +48 -13
  13. package/src/BackendDrivers/CollaborationServerDriver.ts +23 -2
  14. package/src/ChangeManager.ts +42 -18
  15. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +64 -5
  16. package/src/FeatureDetailsWidget/Attributes.tsx +8 -3
  17. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +70 -81
  18. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +946 -190
  19. package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +4 -0
  20. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +61 -73
  21. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +55 -211
  22. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +562 -108
  23. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +78 -14
  24. package/src/LinearApolloDisplay/glyphs/Glyph.ts +15 -9
  25. package/src/LinearApolloDisplay/stateModel/base.ts +63 -43
  26. package/src/LinearApolloDisplay/stateModel/layouts.ts +3 -2
  27. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +79 -292
  28. package/src/LinearApolloDisplay/stateModel/rendering.ts +45 -344
  29. package/src/LinearApolloReferenceSequenceDisplay/components/LinearApolloReferenceSequenceDisplay.tsx +87 -0
  30. package/src/LinearApolloReferenceSequenceDisplay/components/index.ts +1 -0
  31. package/src/LinearApolloReferenceSequenceDisplay/configSchema.ts +7 -0
  32. package/src/LinearApolloReferenceSequenceDisplay/index.ts +3 -0
  33. package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +227 -0
  34. package/src/LinearApolloReferenceSequenceDisplay/stateModel/index.ts +25 -0
  35. package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +481 -0
  36. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +102 -40
  37. package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +12 -20
  38. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +382 -243
  39. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +12 -8
  40. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +83 -4
  41. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +23 -11
  42. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +118 -123
  43. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +53 -63
  44. package/src/OntologyManager/index.ts +4 -1
  45. package/src/TabularEditor/HybridGrid/Feature.tsx +20 -14
  46. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +7 -5
  47. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +108 -16
  48. package/src/components/AddAssembly.tsx +1 -1
  49. package/src/components/AddAssemblyAliases.tsx +114 -0
  50. package/src/components/AddChildFeature.tsx +7 -7
  51. package/src/components/AddFeature.tsx +20 -15
  52. package/src/components/AddRefSeqAliases.tsx +9 -9
  53. package/src/components/CopyFeature.tsx +4 -4
  54. package/src/components/CreateApolloAnnotation.tsx +335 -151
  55. package/src/components/DeleteAssembly.tsx +1 -1
  56. package/src/components/DeleteFeature.tsx +358 -11
  57. package/src/components/DownloadGFF3.tsx +20 -1
  58. package/src/components/EditZoomThresholdDialog.tsx +69 -0
  59. package/src/components/FilterFeatures.tsx +7 -7
  60. package/src/components/FilterTranscripts.tsx +86 -0
  61. package/src/components/ImportFeatures.tsx +1 -1
  62. package/src/components/ManageChecks.tsx +1 -1
  63. package/src/components/MergeExons.tsx +193 -0
  64. package/src/components/MergeTranscripts.tsx +182 -0
  65. package/src/components/OntologyTermMultiSelect.tsx +11 -11
  66. package/src/components/OpenLocalFile.tsx +11 -7
  67. package/src/components/SplitExon.tsx +134 -0
  68. package/src/components/ViewCheckResults.tsx +1 -1
  69. package/src/components/index.ts +4 -0
  70. package/src/config.ts +11 -0
  71. package/src/extensions/annotationFromJBrowseFeature.ts +2 -0
  72. package/src/extensions/annotationFromPileup.ts +99 -89
  73. package/src/index.ts +42 -105
  74. package/src/makeDisplayComponent.tsx +0 -1
  75. package/src/menus/index.ts +1 -0
  76. package/src/{ApolloInternetAccount/addMenuItems.ts → menus/topLevelMenu.ts} +60 -33
  77. package/src/menus/topLevelMenuAdmin.ts +154 -0
  78. package/src/session/session.ts +163 -104
  79. package/src/util/annotationFeatureUtils.ts +59 -0
  80. package/src/util/copyToClipboard.ts +21 -0
  81. package/src/util/displayUtils.ts +149 -0
  82. package/src/util/glyphUtils.ts +201 -0
  83. package/src/util/index.ts +2 -0
  84. package/src/util/mouseEventsUtils.ts +145 -0
@@ -1,9 +1,18 @@
1
1
  import { type AnnotationFeature } from '@apollo-annotation/mst'
2
+ import { type MenuItem } from '@jbrowse/core/ui'
3
+ import { alpha } from '@mui/material'
2
4
 
5
+ import {
6
+ type MousePositionWithFeature,
7
+ containsSelectedFeature,
8
+ isMousePositionWithFeature,
9
+ } from '../../util'
10
+ import { getRelatedFeatures } from '../../util/annotationFeatureUtils'
3
11
  import { type LinearApolloDisplay } from '../stateModel'
12
+ import { type LinearApolloDisplayMouseEvents } from '../stateModel/mouseEvents'
4
13
  import { type LinearApolloDisplayRendering } from '../stateModel/rendering'
5
14
 
6
- import { boxGlyph, drawBox, isSelectedFeature } from './BoxGlyph'
15
+ import { boxGlyph, drawBox } from './BoxGlyph'
7
16
  import { type Glyph } from './Glyph'
8
17
 
9
18
  function featuresForRow(feature: AnnotationFeature): AnnotationFeature[][] {
@@ -27,9 +36,13 @@ function draw(
27
36
  stateModel: LinearApolloDisplayRendering,
28
37
  displayedRegionIndex: number,
29
38
  ) {
39
+ const { selectedFeature } = stateModel
30
40
  for (let i = 0; i < getRowCount(feature); i++) {
31
41
  drawRow(ctx, feature, row + i, row, stateModel, displayedRegionIndex)
32
42
  }
43
+ if (selectedFeature && containsSelectedFeature(feature, selectedFeature)) {
44
+ drawHighlight(stateModel, ctx, selectedFeature)
45
+ }
33
46
  }
34
47
 
35
48
  function drawRow(
@@ -53,7 +66,7 @@ function drawFeature(
53
66
  stateModel: LinearApolloDisplayRendering,
54
67
  displayedRegionIndex: number,
55
68
  ) {
56
- const { apolloRowHeight: heightPx, lgv, session } = stateModel
69
+ const { apolloRowHeight: heightPx, lgv, theme } = stateModel
57
70
  const { bpPerPx, displayedRegions, offsetPx } = lgv
58
71
  const displayedRegion = displayedRegions[displayedRegionIndex]
59
72
  const minX =
@@ -63,13 +76,11 @@ function drawFeature(
63
76
  regionNumber: displayedRegionIndex,
64
77
  })?.offsetPx ?? 0) - offsetPx
65
78
  const { reversed } = displayedRegion
66
- const { apolloSelectedFeature } = session
67
79
  const widthPx = feature.length / bpPerPx
68
80
  const startPx = reversed ? minX - widthPx : minX
69
81
  const top = row * heightPx
70
82
  const rowCount = getRowCount(feature)
71
- const isSelected = isSelectedFeature(feature, apolloSelectedFeature)
72
- const groupingColor = isSelected ? 'rgba(130,0,0,0.45)' : 'rgba(255,0,0,0.25)'
83
+ const groupingColor = alpha(theme.palette.background.paper, 0.6)
73
84
  if (rowCount > 1) {
74
85
  // draw background that encapsulates all child features
75
86
  const featureHeight = rowCount * heightPx
@@ -78,15 +89,14 @@ function drawFeature(
78
89
  boxGlyph.draw(ctx, feature, row, stateModel, displayedRegionIndex)
79
90
  }
80
91
 
81
- function drawHover(
82
- stateModel: LinearApolloDisplay,
92
+ function drawHighlight(
93
+ stateModel: LinearApolloDisplayRendering,
83
94
  ctx: CanvasRenderingContext2D,
95
+ feature: AnnotationFeature,
96
+ selected = false,
84
97
  ) {
85
- const { apolloHover, apolloRowHeight, lgv } = stateModel
86
- if (!apolloHover) {
87
- return
88
- }
89
- const { feature } = apolloHover
98
+ const { apolloRowHeight, lgv, theme } = stateModel
99
+
90
100
  const position = stateModel.getFeatureLayoutPosition(feature)
91
101
  if (!position) {
92
102
  return
@@ -104,10 +114,23 @@ function drawHover(
104
114
  })?.offsetPx ?? 0) - offsetPx
105
115
  const top = (layoutRow + featureRow) * apolloRowHeight
106
116
  const widthPx = length / bpPerPx
107
- ctx.fillStyle = 'rgba(0,0,0,0.2)'
117
+ ctx.fillStyle = selected
118
+ ? theme.palette.action.disabled
119
+ : theme.palette.action.focus
108
120
  ctx.fillRect(startPx, top, widthPx, apolloRowHeight * getRowCount(feature))
109
121
  }
110
122
 
123
+ function drawHover(
124
+ stateModel: LinearApolloDisplay,
125
+ ctx: CanvasRenderingContext2D,
126
+ ) {
127
+ const { hoveredFeature } = stateModel
128
+ if (!hoveredFeature) {
129
+ return
130
+ }
131
+ drawHighlight(stateModel, ctx, hoveredFeature.feature)
132
+ }
133
+
111
134
  function getFeatureFromLayout(
112
135
  feature: AnnotationFeature,
113
136
  bp: number,
@@ -130,12 +153,52 @@ function getRowForFeature(
130
153
  return
131
154
  }
132
155
 
156
+ function getContextMenuItems(
157
+ display: LinearApolloDisplayMouseEvents,
158
+ mousePosition: MousePositionWithFeature,
159
+ ): MenuItem[] {
160
+ const { hoveredFeature, session } = display
161
+ const menuItems: MenuItem[] = []
162
+ if (!hoveredFeature) {
163
+ return menuItems
164
+ }
165
+ const { featureTypeOntology } = session.apolloDataStore.ontologyManager
166
+ if (!featureTypeOntology) {
167
+ throw new Error('featureTypeOntology is undefined')
168
+ }
169
+ const sourceFeatureMenuItems = boxGlyph.getContextMenuItems(
170
+ display,
171
+ mousePosition,
172
+ )
173
+ menuItems.push({
174
+ label: hoveredFeature.feature.type,
175
+ subMenu: sourceFeatureMenuItems,
176
+ })
177
+ if (isMousePositionWithFeature(mousePosition)) {
178
+ const { bp, feature } = mousePosition
179
+ for (const relative of getRelatedFeatures(feature, bp)) {
180
+ if (relative._id === hoveredFeature.feature._id) {
181
+ continue
182
+ }
183
+ const contextMenuItemsForFeature = boxGlyph.getContextMenuItemsForFeature(
184
+ display,
185
+ relative,
186
+ )
187
+ menuItems.push({
188
+ label: relative.type,
189
+ subMenu: contextMenuItemsForFeature,
190
+ })
191
+ }
192
+ }
193
+ return menuItems
194
+ }
195
+
133
196
  // False positive here, none of these functions use "this"
134
197
  /* eslint-disable @typescript-eslint/unbound-method */
135
198
  const {
136
199
  drawDragPreview,
137
200
  drawTooltip,
138
- getContextMenuItems,
201
+ getContextMenuItemsForFeature,
139
202
  onMouseDown,
140
203
  onMouseLeave,
141
204
  onMouseMove,
@@ -148,6 +211,7 @@ export const genericChildGlyph: Glyph = {
148
211
  drawDragPreview,
149
212
  drawHover,
150
213
  drawTooltip,
214
+ getContextMenuItemsForFeature,
151
215
  getContextMenuItems,
152
216
  getFeatureFromLayout,
153
217
  getRowCount,
@@ -2,10 +2,8 @@ import { type AnnotationFeature } from '@apollo-annotation/mst'
2
2
  import { type MenuItem } from '@jbrowse/core/ui'
3
3
 
4
4
  import { type OntologyRecord } from '../../OntologyManager'
5
- import {
6
- type LinearApolloDisplayMouseEvents,
7
- type MousePositionWithFeatureAndGlyph,
8
- } from '../stateModel/mouseEvents'
5
+ import { type MousePositionWithFeature } from '../../util'
6
+ import { type LinearApolloDisplayMouseEvents } from '../stateModel/mouseEvents'
9
7
  import { type LinearApolloDisplayRendering } from '../stateModel/rendering'
10
8
  import { type CanvasMouseEvent } from '../types'
11
9
 
@@ -49,25 +47,25 @@ export interface Glyph {
49
47
 
50
48
  onMouseDown(
51
49
  display: LinearApolloDisplayMouseEvents,
52
- currentMousePosition: MousePositionWithFeatureAndGlyph,
50
+ currentMousePosition: MousePositionWithFeature,
53
51
  event: CanvasMouseEvent,
54
52
  ): void
55
53
 
56
54
  onMouseMove(
57
55
  display: LinearApolloDisplayMouseEvents,
58
- currentMousePosition: MousePositionWithFeatureAndGlyph,
56
+ currentMousePosition: MousePositionWithFeature,
59
57
  event: CanvasMouseEvent,
60
58
  ): void
61
59
 
62
60
  onMouseLeave(
63
61
  display: LinearApolloDisplayMouseEvents,
64
- currentMousePosition: MousePositionWithFeatureAndGlyph,
62
+ currentMousePosition: MousePositionWithFeature,
65
63
  event: CanvasMouseEvent,
66
64
  ): void
67
65
 
68
66
  onMouseUp(
69
67
  display: LinearApolloDisplayMouseEvents,
70
- currentMousePosition: MousePositionWithFeatureAndGlyph,
68
+ currentMousePosition: MousePositionWithFeature,
71
69
  event: CanvasMouseEvent,
72
70
  ): void
73
71
 
@@ -76,5 +74,13 @@ export interface Glyph {
76
74
  context: CanvasRenderingContext2D,
77
75
  ): void
78
76
 
79
- getContextMenuItems(display: LinearApolloDisplayMouseEvents): MenuItem[]
77
+ getContextMenuItemsForFeature(
78
+ display: LinearApolloDisplayMouseEvents,
79
+ sourceFeature: AnnotationFeature,
80
+ ): MenuItem[]
81
+
82
+ getContextMenuItems(
83
+ display: LinearApolloDisplayMouseEvents,
84
+ currentMousePosition: MousePositionWithFeature,
85
+ ): MenuItem[]
80
86
  }
@@ -10,6 +10,7 @@ import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/con
10
10
  import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes'
11
11
  import {
12
12
  type AbstractSessionModel,
13
+ type SessionWithWidgets,
13
14
  getContainingView,
14
15
  getSession,
15
16
  } from '@jbrowse/core/util'
@@ -21,8 +22,9 @@ import { addDisposer, cast, getRoot, getSnapshot, types } from 'mobx-state-tree'
21
22
 
22
23
  import { type ApolloInternetAccountModel } from '../../ApolloInternetAccount/model'
23
24
  import { FilterFeatures } from '../../components/FilterFeatures'
24
- import { type ApolloSessionModel } from '../../session'
25
+ import { type ApolloSessionModel, type HoveredFeature } from '../../session'
25
26
  import { type ApolloRootModel } from '../../types'
27
+ import { EditZoomThresholdDialog } from '../../util/displayUtils'
26
28
 
27
29
  const minDisplayHeight = 20
28
30
 
@@ -36,9 +38,8 @@ export function baseModelFactory(
36
38
  configuration: ConfigurationReference(configSchema),
37
39
  graphical: true,
38
40
  table: false,
39
- showStartCodons: false,
40
- showStopCodons: true,
41
- highContrast: false,
41
+ showCheckResults: true,
42
+ zoomThreshold: 200,
42
43
  heightPreConfig: types.maybe(
43
44
  types.refinement(
44
45
  'displayHeight',
@@ -73,16 +74,19 @@ export function baseModelFactory(
73
74
  return self.heightPreConfig
74
75
  }
75
76
  if (self.graphical && self.table) {
76
- return 500
77
+ return 400
77
78
  }
78
79
  if (self.graphical) {
79
- return 200
80
+ return 100
80
81
  }
81
- return 300
82
+ return 200
82
83
  },
83
84
  get loading() {
84
85
  return self.loadingState
85
86
  },
87
+ get zoomThresholdSetting() {
88
+ return self.zoomThreshold ?? getConf(self, 'zoomThreshold')
89
+ },
86
90
  }))
87
91
  .views((self) => ({
88
92
  get rendererTypeName() {
@@ -103,7 +107,7 @@ export function baseModelFactory(
103
107
  return regions
104
108
  },
105
109
  regionCannotBeRendered(/* region */) {
106
- if (self.lgv && self.lgv.bpPerPx >= 200) {
110
+ if (self.lgv && self.lgv.bpPerPx >= self.zoomThreshold) {
107
111
  return 'Zoom in to see annotations'
108
112
  }
109
113
  return
@@ -145,6 +149,10 @@ export function baseModelFactory(
145
149
  return (self.session as unknown as ApolloSessionModel)
146
150
  .apolloSelectedFeature
147
151
  },
152
+ get hoveredFeature(): HoveredFeature | undefined {
153
+ return (self.session as unknown as ApolloSessionModel)
154
+ .apolloHoveredFeature
155
+ },
148
156
  }))
149
157
  .actions((self) => ({
150
158
  setScrollTop(scrollTop: number) {
@@ -171,14 +179,8 @@ export function baseModelFactory(
171
179
  self.graphical = true
172
180
  self.table = true
173
181
  },
174
- toggleShowStartCodons() {
175
- self.showStartCodons = !self.showStartCodons
176
- },
177
- toggleShowStopCodons() {
178
- self.showStopCodons = !self.showStopCodons
179
- },
180
- toggleHighContrast() {
181
- self.highContrast = !self.highContrast
182
+ toggleShowCheckResults() {
183
+ self.showCheckResults = !self.showCheckResults
182
184
  },
183
185
  updateFilteredFeatureTypes(types: string[]) {
184
186
  self.filteredFeatureTypes = cast(types)
@@ -186,18 +188,15 @@ export function baseModelFactory(
186
188
  setLoading(loading: boolean) {
187
189
  self.loadingState = loading
188
190
  },
191
+ setZoomThresholdSetting({ zoomThreshold }: { zoomThreshold: number }) {
192
+ self.zoomThreshold = zoomThreshold
193
+ },
189
194
  }))
190
195
  .views((self) => {
191
196
  const { filteredFeatureTypes, trackMenuItems: superTrackMenuItems } = self
192
197
  return {
193
198
  trackMenuItems() {
194
- const {
195
- graphical,
196
- table,
197
- showStartCodons,
198
- showStopCodons,
199
- highContrast,
200
- } = self
199
+ const { graphical, table, showCheckResults } = self
201
200
  return [
202
201
  ...superTrackMenuItems(),
203
202
  {
@@ -229,27 +228,20 @@ export function baseModelFactory(
229
228
  },
230
229
  },
231
230
  {
232
- label: 'Show start codons',
231
+ label: 'Check Results',
233
232
  type: 'checkbox',
234
- checked: showStartCodons,
233
+ checked: showCheckResults,
235
234
  onClick: () => {
236
- self.toggleShowStartCodons()
235
+ self.toggleShowCheckResults()
237
236
  },
238
237
  },
239
238
  {
240
- label: 'Show stop codons',
241
- type: 'checkbox',
242
- checked: showStopCodons,
239
+ label: 'Change zoom threshold',
243
240
  onClick: () => {
244
- self.toggleShowStopCodons()
245
- },
246
- },
247
- {
248
- label: 'Use high contrast colors',
249
- type: 'checkbox',
250
- checked: highContrast,
251
- onClick: () => {
252
- self.toggleHighContrast()
241
+ getSession(self).queueDialog((handleClose) => [
242
+ EditZoomThresholdDialog,
243
+ { model: self, handleClose },
244
+ ])
253
245
  },
254
246
  },
255
247
  ],
@@ -285,6 +277,39 @@ export function baseModelFactory(
285
277
  self.session as unknown as ApolloSessionModel
286
278
  ).apolloSetSelectedFeature(feature)
287
279
  },
280
+ setHoveredFeature(hoveredFeature?: HoveredFeature) {
281
+ ;(
282
+ self.session as unknown as ApolloSessionModel
283
+ ).apolloSetHoveredFeature(hoveredFeature)
284
+ },
285
+ showFeatureDetailsWidget(
286
+ feature: AnnotationFeature,
287
+ customWidgetNameAndId?: [string, string],
288
+ ) {
289
+ const [region] = self.regions
290
+ const { assemblyName, refName } = region
291
+ const assembly = self.getAssemblyId(assemblyName)
292
+ if (!assembly) {
293
+ return
294
+ }
295
+ const { session } = self
296
+ const { changeManager } = session.apolloDataStore
297
+ const [widgetName, widgetId] = customWidgetNameAndId ?? [
298
+ 'ApolloFeatureDetailsWidget',
299
+ 'apolloFeatureDetailsWidget',
300
+ ]
301
+ const apolloFeatureWidget = (
302
+ session as unknown as SessionWithWidgets
303
+ ).addWidget(widgetName, widgetId, {
304
+ feature,
305
+ assembly,
306
+ refName,
307
+ changeManager,
308
+ })
309
+ ;(session as unknown as SessionWithWidgets).showWidget(
310
+ apolloFeatureWidget,
311
+ )
312
+ },
288
313
  afterAttach() {
289
314
  addDisposer(
290
315
  self,
@@ -303,11 +328,6 @@ export function baseModelFactory(
303
328
  self.setLoading(false)
304
329
  }, 1000)
305
330
  })
306
- if (self.lgv.bpPerPx <= 3) {
307
- void (
308
- self.session as unknown as ApolloSessionModel
309
- ).apolloDataStore.loadRefSeq(self.regions)
310
- }
311
331
  },
312
332
  { name: 'LinearApolloDisplayLoadFeatures', delay: 1000 },
313
333
  ),
@@ -63,10 +63,11 @@ export function layoutsModelFactory(
63
63
  return self.seenFeatures.get(id)
64
64
  },
65
65
  getGlyph(feature: AnnotationFeature) {
66
- if (feature.looksLikeGene) {
66
+ const { topLevelFeature } = feature
67
+ if (topLevelFeature.looksLikeGene) {
67
68
  return geneGlyph
68
69
  }
69
- if (feature.children?.size) {
70
+ if (topLevelFeature.children?.size) {
70
71
  return genericChildGlyph
71
72
  }
72
73
  return boxGlyph