@apollo-annotation/jbrowse-plugin-apollo 0.3.12 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/dist/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.d.ts +1 -1
  2. package/dist/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.d.ts.map +1 -1
  3. package/dist/BackendDrivers/BackendDriver.d.ts +29 -4
  4. package/dist/BackendDrivers/BackendDriver.d.ts.map +1 -1
  5. package/dist/BackendDrivers/CollaborationServerDriver.d.ts +3 -1
  6. package/dist/BackendDrivers/CollaborationServerDriver.d.ts.map +1 -1
  7. package/dist/BackendDrivers/LocalDriver/LocalDriver.d.ts +22 -0
  8. package/dist/BackendDrivers/LocalDriver/LocalDriver.d.ts.map +1 -0
  9. package/dist/BackendDrivers/LocalDriver/db.d.ts +4 -0
  10. package/dist/BackendDrivers/LocalDriver/db.d.ts.map +1 -0
  11. package/dist/BackendDrivers/index.d.ts +1 -2
  12. package/dist/BackendDrivers/index.d.ts.map +1 -1
  13. package/dist/ChangeManager.d.ts +3 -3
  14. package/dist/ChangeManager.d.ts.map +1 -1
  15. package/dist/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.d.ts +0 -6
  16. package/dist/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.d.ts.map +1 -1
  17. package/dist/FeatureDetailsWidget/TranscriptWidgetEditLocation.d.ts.map +1 -1
  18. package/dist/FeatureDetailsWidget/model.d.ts +0 -2
  19. package/dist/FeatureDetailsWidget/model.d.ts.map +1 -1
  20. package/dist/LinearApolloDisplay/components/CheckResultWarnings.d.ts.map +1 -1
  21. package/dist/LinearApolloDisplay/components/LinearApolloDisplay.d.ts.map +1 -1
  22. package/dist/LinearApolloDisplay/components/OverlayCanvas.d.ts +7 -0
  23. package/dist/LinearApolloDisplay/components/OverlayCanvas.d.ts.map +1 -0
  24. package/dist/LinearApolloDisplay/components/Tooltip.d.ts +10 -0
  25. package/dist/LinearApolloDisplay/components/Tooltip.d.ts.map +1 -0
  26. package/dist/LinearApolloDisplay/glyphs/BoxGlyph.d.ts +0 -1
  27. package/dist/LinearApolloDisplay/glyphs/BoxGlyph.d.ts.map +1 -1
  28. package/dist/LinearApolloDisplay/glyphs/CDSGlyph.d.ts +3 -0
  29. package/dist/LinearApolloDisplay/glyphs/CDSGlyph.d.ts.map +1 -0
  30. package/dist/LinearApolloDisplay/glyphs/ExonGlyph.d.ts +3 -0
  31. package/dist/LinearApolloDisplay/glyphs/ExonGlyph.d.ts.map +1 -0
  32. package/dist/LinearApolloDisplay/glyphs/GeneGlyph.d.ts.map +1 -1
  33. package/dist/LinearApolloDisplay/glyphs/GenericChildGlyph.d.ts.map +1 -1
  34. package/dist/LinearApolloDisplay/glyphs/Glyph.d.ts +26 -20
  35. package/dist/LinearApolloDisplay/glyphs/Glyph.d.ts.map +1 -1
  36. package/dist/LinearApolloDisplay/glyphs/TranscriptGlyph.d.ts +3 -0
  37. package/dist/LinearApolloDisplay/glyphs/TranscriptGlyph.d.ts.map +1 -0
  38. package/dist/LinearApolloDisplay/glyphs/util.d.ts +13 -0
  39. package/dist/LinearApolloDisplay/glyphs/util.d.ts.map +1 -1
  40. package/dist/LinearApolloDisplay/stateModel/base.d.ts +17 -0
  41. package/dist/LinearApolloDisplay/stateModel/base.d.ts.map +1 -1
  42. package/dist/LinearApolloDisplay/stateModel/index.d.ts +35 -17
  43. package/dist/LinearApolloDisplay/stateModel/index.d.ts.map +1 -1
  44. package/dist/LinearApolloDisplay/stateModel/layouts.d.ts +29 -7
  45. package/dist/LinearApolloDisplay/stateModel/layouts.d.ts.map +1 -1
  46. package/dist/LinearApolloDisplay/stateModel/mouseEvents.d.ts +69 -23
  47. package/dist/LinearApolloDisplay/stateModel/mouseEvents.d.ts.map +1 -1
  48. package/dist/LinearApolloDisplay/stateModel/rendering.d.ts +26 -9
  49. package/dist/LinearApolloDisplay/stateModel/rendering.d.ts.map +1 -1
  50. package/dist/LinearApolloReferenceSequenceDisplay/stateModel/base.d.ts +6 -0
  51. package/dist/LinearApolloReferenceSequenceDisplay/stateModel/base.d.ts.map +1 -1
  52. package/dist/LinearApolloReferenceSequenceDisplay/stateModel/index.d.ts +6 -0
  53. package/dist/LinearApolloReferenceSequenceDisplay/stateModel/index.d.ts.map +1 -1
  54. package/dist/LinearApolloReferenceSequenceDisplay/stateModel/rendering.d.ts +6 -0
  55. package/dist/LinearApolloReferenceSequenceDisplay/stateModel/rendering.d.ts.map +1 -1
  56. package/dist/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.d.ts.map +1 -1
  57. package/dist/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.d.ts.map +1 -1
  58. package/dist/LinearApolloSixFrameDisplay/glyphs/Glyph.d.ts +1 -1
  59. package/dist/LinearApolloSixFrameDisplay/glyphs/Glyph.d.ts.map +1 -1
  60. package/dist/LinearApolloSixFrameDisplay/stateModel/layouts.d.ts.map +1 -1
  61. package/dist/LinearApolloSixFrameDisplay/stateModel/rendering.d.ts.map +1 -1
  62. package/dist/OntologyManager/OntologyStore/fulltext.d.ts +1 -1
  63. package/dist/OntologyManager/OntologyStore/fulltext.d.ts.map +1 -1
  64. package/dist/OntologyManager/OntologyStore/index.d.ts +2 -2
  65. package/dist/OntologyManager/OntologyStore/index.d.ts.map +1 -1
  66. package/dist/OntologyManager/OntologyStore/indexeddb-storage.d.ts +1 -1
  67. package/dist/OntologyManager/OntologyStore/indexeddb-storage.d.ts.map +1 -1
  68. package/dist/OntologyManager/OntologyStore/types.d.ts +18 -0
  69. package/dist/OntologyManager/OntologyStore/types.d.ts.map +1 -0
  70. package/dist/TabularEditor/HybridGrid/featureContextMenuItems.d.ts.map +1 -1
  71. package/dist/components/AddChildFeature.d.ts.map +1 -1
  72. package/dist/components/ColorFeature.d.ts +13 -0
  73. package/dist/components/ColorFeature.d.ts.map +1 -0
  74. package/dist/components/CreateApolloAnnotation.d.ts.map +1 -1
  75. package/dist/components/DownloadGFF3.d.ts +4 -1
  76. package/dist/components/DownloadGFF3.d.ts.map +1 -1
  77. package/dist/components/DuplicateTranscript.d.ts.map +1 -1
  78. package/dist/components/ViewChangeLog.d.ts +2 -1
  79. package/dist/components/ViewChangeLog.d.ts.map +1 -1
  80. package/dist/components/ViewCheckResults.d.ts +2 -1
  81. package/dist/components/ViewCheckResults.d.ts.map +1 -1
  82. package/dist/components/index.d.ts +1 -1
  83. package/dist/components/index.d.ts.map +1 -1
  84. package/dist/config.d.ts +4 -0
  85. package/dist/config.d.ts.map +1 -0
  86. package/dist/extensions/annotationFromJBrowseFeature.d.ts.map +1 -1
  87. package/dist/extensions/annotationFromPileup.d.ts.map +1 -1
  88. package/dist/index.d.ts +11 -0
  89. package/dist/index.d.ts.map +1 -0
  90. package/dist/index.esm.js +6325 -5997
  91. package/dist/index.esm.js.map +1 -1
  92. package/dist/jbrowse-plugin-apollo.cjs.development.js +5869 -5541
  93. package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
  94. package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
  95. package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
  96. package/dist/jbrowse-plugin-apollo.umd.development.js +16782 -25897
  97. package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
  98. package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
  99. package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
  100. package/dist/makeDisplayComponent.d.ts.map +1 -1
  101. package/dist/menus/Icons.d.ts +3 -0
  102. package/dist/menus/Icons.d.ts.map +1 -0
  103. package/dist/menus/topLevelMenu.d.ts.map +1 -1
  104. package/dist/session/changeHandlers.d.ts +9 -0
  105. package/dist/session/changeHandlers.d.ts.map +1 -0
  106. package/dist/util/annotationFeatureUtils.d.ts +2 -1
  107. package/dist/util/annotationFeatureUtils.d.ts.map +1 -1
  108. package/dist/util/glyphUtils.d.ts +3 -3
  109. package/dist/util/glyphUtils.d.ts.map +1 -1
  110. package/dist/util/index.d.ts +0 -1
  111. package/dist/util/index.d.ts.map +1 -1
  112. package/package.json +4 -4
  113. package/src/ApolloInternetAccount/model.ts +68 -4
  114. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +6 -3
  115. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +1 -1
  116. package/src/BackendDrivers/BackendDriver.ts +36 -3
  117. package/src/BackendDrivers/CollaborationServerDriver.ts +78 -23
  118. package/src/BackendDrivers/LocalDriver/LocalDriver.ts +367 -0
  119. package/src/BackendDrivers/LocalDriver/db.ts +37 -0
  120. package/src/BackendDrivers/index.ts +1 -2
  121. package/src/ChangeManager.ts +27 -25
  122. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +1 -1
  123. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +69 -53
  124. package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +1 -5
  125. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +95 -115
  126. package/src/LinearApolloDisplay/components/OverlayCanvas.tsx +76 -0
  127. package/src/LinearApolloDisplay/components/Tooltip.tsx +42 -0
  128. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +60 -302
  129. package/src/LinearApolloDisplay/glyphs/CDSGlyph.ts +145 -0
  130. package/src/LinearApolloDisplay/glyphs/ExonGlyph.ts +212 -0
  131. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +65 -999
  132. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +71 -181
  133. package/src/LinearApolloDisplay/glyphs/Glyph.ts +42 -66
  134. package/src/LinearApolloDisplay/glyphs/TranscriptGlyph.ts +291 -0
  135. package/src/LinearApolloDisplay/glyphs/util.ts +87 -0
  136. package/src/LinearApolloDisplay/stateModel/base.ts +83 -0
  137. package/src/LinearApolloDisplay/stateModel/layouts.ts +198 -138
  138. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +252 -158
  139. package/src/LinearApolloDisplay/stateModel/rendering.ts +103 -21
  140. package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +3 -3
  141. package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +20 -2
  142. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +7 -2
  143. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +8 -13
  144. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +1 -1
  145. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +4 -3
  146. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +1 -1
  147. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +2 -1
  148. package/src/OntologyManager/OntologyStore/__snapshots__/index.test.ts.snap +18262 -8519
  149. package/src/OntologyManager/OntologyStore/fulltext.ts +1 -2
  150. package/src/OntologyManager/OntologyStore/index.test.ts +5 -2
  151. package/src/OntologyManager/OntologyStore/index.ts +7 -8
  152. package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +2 -2
  153. package/src/OntologyManager/OntologyStore/types.ts +27 -0
  154. package/src/OntologyManager/index.ts +15 -26
  155. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +4 -5
  156. package/src/components/AddChildFeature.tsx +15 -8
  157. package/src/components/ColorFeature.tsx +167 -0
  158. package/src/components/CreateApolloAnnotation.tsx +35 -9
  159. package/src/components/DownloadGFF3.tsx +92 -121
  160. package/src/components/DuplicateTranscript.tsx +10 -0
  161. package/src/components/ViewChangeLog.tsx +123 -83
  162. package/src/components/ViewCheckResults.tsx +15 -73
  163. package/src/components/index.ts +1 -1
  164. package/src/config.ts +37 -19
  165. package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -1
  166. package/src/extensions/annotationFromJBrowseFeature.ts +91 -63
  167. package/src/extensions/annotationFromPileup.ts +40 -40
  168. package/src/index.ts +45 -1
  169. package/src/makeDisplayComponent.tsx +10 -3
  170. package/src/menus/Icons.tsx +49 -0
  171. package/src/menus/topLevelMenu.ts +24 -96
  172. package/src/session/ClientDataStore.ts +16 -17
  173. package/src/session/changeHandlers.ts +261 -0
  174. package/src/session/session.ts +77 -46
  175. package/src/util/annotationFeatureUtils.ts +29 -1
  176. package/src/util/glyphUtils.ts +74 -31
  177. package/src/util/index.ts +0 -1
  178. package/dist/BackendDrivers/DesktopFileDriver.d.ts +0 -160
  179. package/dist/BackendDrivers/DesktopFileDriver.d.ts.map +0 -1
  180. package/dist/BackendDrivers/InMemoryFileDriver.d.ts +0 -162
  181. package/dist/BackendDrivers/InMemoryFileDriver.d.ts.map +0 -1
  182. package/dist/LinearApolloDisplay/glyphs/index.d.ts +0 -4
  183. package/dist/LinearApolloDisplay/glyphs/index.d.ts.map +0 -1
  184. package/dist/components/OpenLocalFile.d.ts +0 -15
  185. package/dist/components/OpenLocalFile.d.ts.map +0 -1
  186. package/dist/util/loadAssemblyIntoClient.d.ts +0 -5
  187. package/dist/util/loadAssemblyIntoClient.d.ts.map +0 -1
  188. package/src/BackendDrivers/DesktopFileDriver.ts +0 -184
  189. package/src/BackendDrivers/InMemoryFileDriver.ts +0 -107
  190. package/src/LinearApolloDisplay/glyphs/index.ts +0 -3
  191. package/src/components/OpenLocalFile.tsx +0 -189
  192. package/src/util/loadAssemblyIntoClient.ts +0 -94
@@ -8,43 +8,22 @@ import { addDisposer, isAlive } from '@jbrowse/mobx-state-tree'
8
8
  import { autorun, observable } from 'mobx'
9
9
 
10
10
  import type { ApolloSessionModel } from '../../session'
11
- import { boxGlyph, geneGlyph, genericChildGlyph } from '../glyphs'
11
+ import {
12
+ isCDSFeature,
13
+ isExonFeature,
14
+ isGeneFeature,
15
+ isTranscriptFeature,
16
+ } from '../../util/glyphUtils'
17
+ import { boxGlyph } from '../glyphs/BoxGlyph'
18
+ import { cdsGlyph } from '../glyphs/CDSGlyph'
19
+ import { exonGlyph } from '../glyphs/ExonGlyph'
20
+ import { geneGlyph } from '../glyphs/GeneGlyph'
21
+ import { genericChildGlyph } from '../glyphs/GenericChildGlyph'
22
+ import type { Layout } from '../glyphs/Glyph'
23
+ import { transcriptGlyph } from '../glyphs/TranscriptGlyph'
12
24
 
13
25
  import { baseModelFactory } from './base'
14
26
 
15
- function getRowsForFeature(
16
- startingRow: number,
17
- rowCount: number,
18
- filledRowLocations: Map<number, [number, number][]>,
19
- ) {
20
- const rowsForFeature = []
21
- for (let i = startingRow; i < startingRow + rowCount; i++) {
22
- const row = filledRowLocations.get(i)
23
- if (row) {
24
- rowsForFeature.push(row)
25
- }
26
- }
27
- return rowsForFeature
28
- }
29
-
30
- function canPlaceFeatureInRows(
31
- rowsForFeature: [number, number][][],
32
- feature: AnnotationFeature,
33
- ) {
34
- for (const rowForFeature of rowsForFeature) {
35
- for (const [rowStart, rowEnd] of rowForFeature) {
36
- if (
37
- doesIntersect2(feature.min, feature.max, rowStart, rowEnd) ||
38
- doesIntersect2(rowStart, rowEnd, feature.min, feature.max)
39
- ) {
40
- return false
41
- }
42
- }
43
- }
44
-
45
- return true
46
- }
47
-
48
27
  export function layoutsModelFactory(
49
28
  pluginManager: PluginManager,
50
29
  configSchema: AnyConfigurationSchemaType,
@@ -63,11 +42,19 @@ export function layoutsModelFactory(
63
42
  return self.seenFeatures.get(id)
64
43
  },
65
44
  getGlyph(feature: AnnotationFeature) {
66
- const { topLevelFeature } = feature
67
- if (topLevelFeature.looksLikeGene) {
45
+ if (isGeneFeature(feature, self.session)) {
68
46
  return geneGlyph
69
47
  }
70
- if (topLevelFeature.children?.size) {
48
+ if (isTranscriptFeature(feature, self.session)) {
49
+ return transcriptGlyph
50
+ }
51
+ if (isExonFeature(feature, self.session)) {
52
+ return exonGlyph
53
+ }
54
+ if (isCDSFeature(feature, self.session)) {
55
+ return cdsGlyph
56
+ }
57
+ if (feature.children?.size) {
71
58
  return genericChildGlyph
72
59
  }
73
60
  return boxGlyph
@@ -82,125 +69,198 @@ export function layoutsModelFactory(
82
69
  },
83
70
  }))
84
71
  .views((self) => ({
85
- get featureLayouts() {
72
+ getCanonicalRefName(assemblyName: string, refSeq: string) {
86
73
  const { assemblyManager } =
87
74
  self.session as unknown as AbstractSessionModel
88
- return self.lgv.displayedRegions.map((region) => {
89
- const assembly = assemblyManager.get(region.assemblyName)
90
- const featureLayout = new Map<number, [number, string][]>()
91
- // Track the occupied coordinates in each row
92
- const filledRowLocations = new Map<number, [number, number][]>()
75
+ const assembly = assemblyManager.get(assemblyName)
76
+ if (!assembly) {
77
+ throw new Error('no assembly in layout')
78
+ }
79
+ const canonicalRefName = assembly.getCanonicalRefName(refSeq)
80
+ if (!canonicalRefName) {
81
+ throw new Error('no canonical refName in layout')
82
+ }
83
+ return canonicalRefName
84
+ },
85
+ }))
86
+ .views((self) => ({
87
+ /**
88
+ * Is a feature in one of the currently displayed regions and also is not
89
+ * currently filtered out by the display.
90
+ */
91
+ isFeatureDisplayed(feature: AnnotationFeature) {
92
+ const canonicalRefName = self.getCanonicalRefName(
93
+ feature.assemblyId,
94
+ feature.refSeq,
95
+ )
96
+ return self.lgv.displayedRegions.some((region) => {
93
97
  const { end, refName, start } = region
94
- for (const [id, feature] of self.seenFeatures.entries()) {
95
- if (!isAlive(feature)) {
96
- self.deleteSeenFeature(id)
97
- continue
98
- }
99
- if (
100
- refName !== assembly?.getCanonicalRefName(feature.refSeq) ||
101
- !doesIntersect2(start, end, feature.min, feature.max) ||
102
- (self.filteredFeatureTypes.length > 0 &&
103
- !self.filteredFeatureTypes.includes(feature.type))
104
- ) {
105
- continue
106
- }
107
- const { featureTypeOntology } =
108
- self.session.apolloDataStore.ontologyManager
109
- if (!featureTypeOntology) {
110
- throw new Error('featureTypeOntology is undefined')
111
- }
112
- const rowCount = self
113
- .getGlyph(feature)
114
- .getRowCount(feature, featureTypeOntology, self.lgv.bpPerPx)
115
- let startingRow = 0
116
- let placed = false
117
- while (!placed) {
118
- let rowsForFeature = getRowsForFeature(
119
- startingRow,
120
- rowCount,
121
- filledRowLocations,
122
- )
123
- if (rowsForFeature.length < rowCount) {
124
- for (let i = 0; i < rowCount - rowsForFeature.length; i++) {
125
- const newRowNumber = filledRowLocations.size
126
- filledRowLocations.set(newRowNumber, [])
127
- featureLayout.set(newRowNumber, [])
128
- }
129
- rowsForFeature = getRowsForFeature(
130
- startingRow,
131
- rowCount,
132
- filledRowLocations,
133
- )
134
- }
135
- if (!canPlaceFeatureInRows(rowsForFeature, feature)) {
136
- startingRow += 1
137
- continue
138
- }
139
- for (
140
- let rowNum = startingRow;
141
- rowNum < startingRow + rowCount;
142
- rowNum++
143
- ) {
144
- filledRowLocations.get(rowNum)?.push([feature.min, feature.max])
145
- const layoutRow = featureLayout.get(rowNum)
146
- layoutRow?.push([rowNum - startingRow, feature._id])
147
- }
148
- placed = true
149
- }
98
+ const hasDisplayedFeatureTypes = self.filteredFeatureTypes.length > 0
99
+ if (
100
+ (!hasDisplayedFeatureTypes ||
101
+ self.filteredFeatureTypes.includes(feature.type)) &&
102
+ canonicalRefName === refName &&
103
+ doesIntersect2(start, end, feature.min, feature.max)
104
+ ) {
105
+ return true
150
106
  }
151
- return featureLayout
107
+ return false
152
108
  })
153
109
  },
154
- getFeatureLayoutPosition(feature: AnnotationFeature) {
155
- const { featureLayouts } = this
156
- const { featureTypeOntology } =
157
- self.session.apolloDataStore.ontologyManager
158
- for (const [idx, layout] of featureLayouts.entries()) {
159
- for (const [layoutRowNum, layoutRow] of layout) {
160
- for (const [featureRowNum, layoutFeatureId] of layoutRow) {
161
- if (featureRowNum !== 0) {
162
- // Same top-level feature in all feature rows, so only need to
163
- // check the first one
164
- continue
165
- }
166
- const layoutFeature =
167
- self.getAnnotationFeatureById(layoutFeatureId)
168
- if (!layoutFeature) {
169
- continue
110
+ }))
111
+ .views((self) => ({
112
+ get layouts(): Map<string, Map<string, Layout>> {
113
+ // Each refName in an assembly gets its own layout so that if a feature
114
+ // is drawn in multiple displayed regions, it has the same layout for
115
+ // each of them
116
+ const layoutByAssemblyAndRefName = new Map<
117
+ string,
118
+ Map<string, Layout>
119
+ >()
120
+ // Go through all the features we know about and add them to th
121
+ for (const [id, feature] of self.seenFeatures.entries()) {
122
+ if (!isAlive(feature)) {
123
+ self.deleteSeenFeature(id)
124
+ continue
125
+ }
126
+ const isDisplayed = self.isFeatureDisplayed(feature)
127
+ if (!isDisplayed) {
128
+ continue
129
+ }
130
+ // This contains layout information for all the feature's sub-features
131
+ // as well
132
+ const featureLayout = self
133
+ .getGlyph(feature)
134
+ // @ts-expect-error ts doesn't understand mst extension
135
+ .getLayout(self, feature)
136
+ const canonicalRefName = self.getCanonicalRefName(
137
+ feature.assemblyId,
138
+ feature.refSeq,
139
+ )
140
+ let layoutForAssembly = layoutByAssemblyAndRefName.get(
141
+ feature.assemblyId,
142
+ )
143
+ if (!layoutForAssembly) {
144
+ layoutForAssembly = new Map<string, Layout>()
145
+ layoutByAssemblyAndRefName.set(
146
+ feature.assemblyId,
147
+ layoutForAssembly,
148
+ )
149
+ }
150
+ const layout = layoutForAssembly.get(canonicalRefName)
151
+ if (!layout) {
152
+ // If this refSeq doesn't have a layout yet, use this feature's
153
+ // layout as a starting layout and move on to the next feature
154
+ layoutForAssembly.set(canonicalRefName, featureLayout)
155
+ continue
156
+ }
157
+ // Check this feature for collisions in the layout, and increase the
158
+ // starting row if needed until there are no collisions. Then place
159
+ // the feature in the layout.
160
+ let startingRowIndex = 0
161
+ placeFeature: while (true) {
162
+ let layoutRow = layout.byRow.at(startingRowIndex)
163
+ if (!layoutRow) {
164
+ // We've increased startingRowIndex to a row that doesn't exist in
165
+ // layout yet. Create new row(s), place the feature in them, and
166
+ // move on to the next feature
167
+ layout.byRow.push(...featureLayout.byRow)
168
+ for (const entry of featureLayout.byFeature.entries()) {
169
+ const [featureId, rowNumber] = entry
170
+ layout.byFeature.set(featureId, rowNumber + startingRowIndex)
170
171
  }
171
- if (feature._id === layoutFeature._id) {
172
- return {
173
- layoutIndex: idx,
174
- layoutRow: layoutRowNum,
175
- featureRow: featureRowNum,
172
+ layout.min = Math.min(layout.min, featureLayout.min)
173
+ layout.max = Math.max(layout.max, featureLayout.max)
174
+ break placeFeature
175
+ }
176
+ // Check this row for collisions. Also check higher rows for
177
+ // collisions if the feature layout takes up more than one row.
178
+ // If there is a collision, set the startingRowIndex to the next
179
+ // row.
180
+ const highestRow = startingRowIndex + featureLayout.byRow.length - 1
181
+ let currentRow = startingRowIndex
182
+ while (layoutRow && startingRowIndex <= highestRow) {
183
+ for (const layoutFeature of layoutRow.values()) {
184
+ if (
185
+ doesIntersect2(
186
+ featureLayout.min,
187
+ featureLayout.max,
188
+ layoutFeature.feature.min,
189
+ layoutFeature.feature.max,
190
+ )
191
+ ) {
192
+ startingRowIndex += 1
193
+ continue placeFeature
176
194
  }
177
195
  }
178
- if (layoutFeature.hasDescendant(feature._id)) {
179
- if (!featureTypeOntology) {
180
- throw new Error('featureTypeOntology is undefined')
181
- }
182
- const row = self
183
- .getGlyph(layoutFeature)
184
- .getRowForFeature(layoutFeature, feature, featureTypeOntology)
185
- if (row !== undefined) {
186
- return {
187
- layoutIndex: idx,
188
- layoutRow: layoutRowNum,
189
- featureRow: row,
190
- }
191
- }
196
+ currentRow += 1
197
+ layoutRow = layout.byRow.at(currentRow)
198
+ }
199
+ // Now we have our startingRowIndex. Place feature in the layout,
200
+ // adding new rows if necessary.
201
+ for (let i = 0; i < featureLayout.byRow.length; i++) {
202
+ const layoutRow = layout.byRow.at(startingRowIndex + i)
203
+ if (layoutRow) {
204
+ layoutRow.push(...featureLayout.byRow[i])
205
+ } else {
206
+ layout.byRow.push(featureLayout.byRow[i])
192
207
  }
193
208
  }
209
+ for (const entry of featureLayout.byFeature.entries()) {
210
+ const [featureId, rowNumber] = entry
211
+ layout.byFeature.set(featureId, rowNumber + startingRowIndex)
212
+ }
213
+ layout.min = Math.min(layout.min, featureLayout.min)
214
+ layout.max = Math.max(layout.max, featureLayout.max)
215
+ break placeFeature
194
216
  }
195
217
  }
196
- return
218
+ return layoutByAssemblyAndRefName
219
+ },
220
+ getRowForFeature(feature: AnnotationFeature) {
221
+ const canonicalRefName = self.getCanonicalRefName(
222
+ feature.assemblyId,
223
+ feature.refSeq,
224
+ )
225
+ return this.layouts
226
+ .get(feature.assemblyId)
227
+ ?.get(canonicalRefName)
228
+ ?.byFeature.get(feature._id)
229
+ },
230
+ getFeaturesAtPosition(
231
+ assemblyName: string,
232
+ refName: string,
233
+ row: number,
234
+ bp: number,
235
+ ): AnnotationFeature[] {
236
+ const assemblyLayouts = this.layouts.get(assemblyName)
237
+ if (!assemblyLayouts) {
238
+ return []
239
+ }
240
+ const layout = assemblyLayouts.get(refName)
241
+ if (!layout) {
242
+ return []
243
+ }
244
+ const layoutRow = layout.byRow.at(row)
245
+ if (!layoutRow) {
246
+ return []
247
+ }
248
+ return layoutRow
249
+ .filter(({ feature }) => {
250
+ return bp >= feature.min && bp <= feature.max
251
+ })
252
+ .map((row) => row.feature)
197
253
  },
198
254
  }))
199
255
  .views((self) => ({
200
- get highestRow() {
256
+ highestRow(assemblyName: string) {
257
+ const assemblyLayouts = self.layouts.get(assemblyName)
258
+ if (!assemblyLayouts) {
259
+ return 0
260
+ }
201
261
  return Math.max(
202
262
  0,
203
- ...self.featureLayouts.map((layout) => Math.max(...layout.keys())),
263
+ ...[...assemblyLayouts.values()].map((layout) => layout.byRow.length),
204
264
  )
205
265
  },
206
266
  }))