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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/index.esm.js +5466 -4490
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +5283 -4318
  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 +6806 -4088
  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 +4 -4
  12. package/src/ApolloInternetAccount/addMenuItems.ts +5 -2
  13. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
  14. package/src/ApolloInternetAccount/components/LoginButtons.tsx +1 -1
  15. package/src/ApolloInternetAccount/components/LoginIcons.tsx +1 -1
  16. package/src/ApolloInternetAccount/configSchema.ts +1 -1
  17. package/src/ApolloInternetAccount/model.ts +11 -10
  18. package/src/ApolloJobModel.ts +1 -1
  19. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +8 -6
  20. package/src/ApolloRefNameAliasAdapter/index.ts +2 -2
  21. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +17 -4
  22. package/src/ApolloSequenceAdapter/index.ts +1 -1
  23. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +8 -7
  24. package/src/ApolloTextSearchAdapter/index.ts +1 -1
  25. package/src/BackendDrivers/BackendDriver.ts +7 -7
  26. package/src/BackendDrivers/CollaborationServerDriver.ts +14 -10
  27. package/src/BackendDrivers/DesktopFileDriver.ts +11 -10
  28. package/src/BackendDrivers/InMemoryFileDriver.ts +10 -6
  29. package/src/ChangeManager.ts +5 -5
  30. package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +92 -20
  31. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +170 -27
  32. package/src/FeatureDetailsWidget/AttributeKey.tsx +50 -0
  33. package/src/FeatureDetailsWidget/AttributeKeySelector.tsx +104 -0
  34. package/src/FeatureDetailsWidget/Attributes.tsx +213 -320
  35. package/src/FeatureDetailsWidget/BasicInformation.tsx +8 -9
  36. package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +104 -0
  37. package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +22 -0
  38. package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +10 -8
  39. package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -1
  40. package/src/FeatureDetailsWidget/Sequence.tsx +18 -35
  41. package/src/FeatureDetailsWidget/StringTextField.tsx +1 -1
  42. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +140 -95
  43. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +600 -0
  44. package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +54 -0
  45. package/src/FeatureDetailsWidget/model.ts +8 -3
  46. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +19 -12
  47. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +19 -41
  48. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +44 -22
  49. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +6 -5
  50. package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -7
  51. package/src/LinearApolloDisplay/stateModel/base.ts +52 -10
  52. package/src/LinearApolloDisplay/stateModel/index.ts +4 -3
  53. package/src/LinearApolloDisplay/stateModel/layouts.ts +8 -34
  54. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +13 -12
  55. package/src/LinearApolloDisplay/stateModel/rendering.ts +63 -31
  56. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +221 -0
  57. package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +40 -0
  58. package/src/LinearApolloSixFrameDisplay/components/index.ts +2 -0
  59. package/src/LinearApolloSixFrameDisplay/configSchema.ts +7 -0
  60. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +821 -0
  61. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +63 -0
  62. package/src/LinearApolloSixFrameDisplay/glyphs/index.ts +1 -0
  63. package/src/LinearApolloSixFrameDisplay/index.ts +2 -0
  64. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +261 -0
  65. package/src/LinearApolloSixFrameDisplay/stateModel/index.ts +27 -0
  66. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +236 -0
  67. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +349 -0
  68. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +199 -0
  69. package/src/LinearApolloSixFrameDisplay/types.ts +1 -0
  70. package/src/OntologyManager/OntologyStore/fulltext-stopwords.ts +10 -1
  71. package/src/OntologyManager/OntologyStore/fulltext.test.ts +1 -1
  72. package/src/OntologyManager/OntologyStore/fulltext.ts +8 -3
  73. package/src/OntologyManager/OntologyStore/index.test.ts +4 -1
  74. package/src/OntologyManager/OntologyStore/index.ts +19 -14
  75. package/src/OntologyManager/OntologyStore/indexeddb-schema.ts +6 -5
  76. package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +11 -5
  77. package/src/OntologyManager/index.ts +10 -6
  78. package/src/OntologyManager/util.ts +3 -2
  79. package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
  80. package/src/TabularEditor/HybridGrid/Feature.tsx +9 -8
  81. package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +1 -1
  82. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +3 -2
  83. package/src/TabularEditor/HybridGrid/NumberCell.tsx +8 -1
  84. package/src/TabularEditor/HybridGrid/ToolBar.tsx +15 -13
  85. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +9 -33
  86. package/src/TabularEditor/TabularEditorPane.tsx +1 -1
  87. package/src/TabularEditor/model.ts +2 -2
  88. package/src/TabularEditor/types.ts +5 -2
  89. package/src/components/AddAssembly.tsx +611 -291
  90. package/src/components/AddChildFeature.tsx +6 -5
  91. package/src/components/AddFeature.tsx +211 -38
  92. package/src/components/AddRefSeqAliases.tsx +14 -12
  93. package/src/components/CopyFeature.tsx +8 -7
  94. package/src/components/CreateApolloAnnotation.tsx +154 -46
  95. package/src/components/DeleteAssembly.tsx +9 -8
  96. package/src/components/DeleteFeature.tsx +5 -4
  97. package/src/components/Dialog.tsx +1 -1
  98. package/src/components/DownloadGFF3.tsx +11 -10
  99. package/src/components/FilterFeatures.tsx +6 -4
  100. package/src/components/ImportFeatures.tsx +7 -6
  101. package/src/components/LogOut.tsx +5 -4
  102. package/src/components/ManageChecks.tsx +9 -8
  103. package/src/components/ManageUsers.tsx +11 -10
  104. package/src/components/OntologyTermAutocomplete.tsx +5 -5
  105. package/src/components/OntologyTermMultiSelect.tsx +9 -6
  106. package/src/components/OpenLocalFile.tsx +4 -3
  107. package/src/components/ViewChangeLog.tsx +7 -6
  108. package/src/components/ViewCheckResults.tsx +8 -7
  109. package/src/components/index.ts +0 -1
  110. package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -0
  111. package/src/extensions/annotationFromJBrowseFeature.ts +14 -12
  112. package/src/extensions/annotationFromPileup.ts +6 -6
  113. package/src/index.ts +33 -50
  114. package/src/makeDisplayComponent.tsx +93 -41
  115. package/src/session/ClientDataStore.ts +21 -17
  116. package/src/session/session.ts +20 -26
  117. package/src/types.ts +4 -4
  118. package/src/util/annotationFeatureUtils.ts +53 -0
  119. package/src/util/index.ts +4 -3
  120. package/src/util/loadAssemblyIntoClient.ts +10 -3
  121. package/src/ApolloSixFrameRenderer/ApolloSixFrameRenderer.tsx +0 -13
  122. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +0 -707
  123. package/src/ApolloSixFrameRenderer/configSchema.ts +0 -7
  124. package/src/ApolloSixFrameRenderer/index.ts +0 -3
  125. package/src/FeatureDetailsWidget/TranscriptBasic.tsx +0 -200
  126. package/src/SixFrameFeatureDisplay/components/TrackLines.tsx +0 -19
  127. package/src/SixFrameFeatureDisplay/components/index.ts +0 -1
  128. package/src/SixFrameFeatureDisplay/configSchema.ts +0 -21
  129. package/src/SixFrameFeatureDisplay/index.ts +0 -2
  130. package/src/SixFrameFeatureDisplay/stateModel.ts +0 -439
  131. package/src/components/ModifyFeatureAttribute.tsx +0 -460
@@ -1,3 +0,0 @@
1
- export { default as ReactComponent } from './components/ApolloRendering'
2
- export { default as configSchema } from './configSchema'
3
- export { default as ApolloSixFrameRenderer } from './ApolloSixFrameRenderer'
@@ -1,200 +0,0 @@
1
- import { AnnotationFeature } from '@apollo-annotation/mst'
2
- import {
3
- LocationEndChange,
4
- LocationStartChange,
5
- } from '@apollo-annotation/shared'
6
- import { AbstractSessionModel, getFrame, revcom } from '@jbrowse/core/util'
7
- import {
8
- Paper,
9
- Typography,
10
- Table,
11
- TableBody,
12
- TableCell,
13
- TableContainer,
14
- TableRow,
15
- useTheme,
16
- } from '@mui/material'
17
- import { observer } from 'mobx-react'
18
- import React from 'react'
19
-
20
- import { ApolloSessionModel } from '../session'
21
- import { NumberTextField } from './NumberTextField'
22
-
23
- export const TranscriptBasicInformation = observer(
24
- function TranscriptBasicInformation({
25
- assembly,
26
- feature,
27
- refName,
28
- session,
29
- }: {
30
- feature: AnnotationFeature
31
- session: ApolloSessionModel
32
- assembly: string
33
- refName: string
34
- }) {
35
- const { notify } = session as unknown as AbstractSessionModel
36
- const currentAssembly = session.apolloDataStore.assemblies.get(assembly)
37
- const refData = currentAssembly?.getByRefName(refName)
38
- const { changeManager } = session.apolloDataStore
39
- const theme = useTheme()
40
-
41
- function handleLocationChange(
42
- oldLocation: number,
43
- newLocation: number,
44
- feature: AnnotationFeature,
45
- isMin: boolean,
46
- ) {
47
- if (!feature.children) {
48
- throw new Error('Transcript should have child features')
49
- }
50
- for (const [, child] of feature.children) {
51
- if (isMin && oldLocation - 1 === child.min) {
52
- const change = new LocationStartChange({
53
- typeName: 'LocationStartChange',
54
- changedIds: [child._id],
55
- featureId: feature._id,
56
- oldStart: oldLocation - 1,
57
- newStart: newLocation - 1,
58
- assembly,
59
- })
60
- changeManager.submit(change).catch(() => {
61
- notify('Error updating feature start position', 'error')
62
- })
63
- return
64
- }
65
- if (!isMin && newLocation === child.max) {
66
- const change = new LocationEndChange({
67
- typeName: 'LocationEndChange',
68
- changedIds: [child._id],
69
- featureId: feature._id,
70
- oldEnd: child.max,
71
- newEnd: newLocation,
72
- assembly,
73
- })
74
- changeManager.submit(change).catch(() => {
75
- notify('Error updating feature start position', 'error')
76
- })
77
- return
78
- }
79
- }
80
- }
81
-
82
- if (!refData) {
83
- return null
84
- }
85
-
86
- let strand, transcriptParts
87
- try {
88
- ;({ strand, transcriptParts } = feature)
89
- } catch {
90
- return null
91
- }
92
- const [firstLocation] = transcriptParts
93
-
94
- const locationData = firstLocation
95
- .map((loc, idx) => {
96
- const { max, min, type } = loc
97
- let label: string = type
98
- if (label === 'threePrimeUTR') {
99
- label = '3` UTR'
100
- } else if (label === 'fivePrimeUTR') {
101
- label = '5` UTR'
102
- }
103
- let fivePrimeSpliceSite
104
- let threePrimeSpliceSite
105
- let frameColor
106
- if (type === 'CDS') {
107
- const { phase } = loc
108
- const frame = getFrame(min, max, strand ?? 1, phase)
109
- frameColor = theme.palette.framesCDS.at(frame)?.main
110
- const previousLoc = firstLocation.at(idx - 1)
111
- const nextLoc = firstLocation.at(idx + 1)
112
- if (strand === 1) {
113
- if (previousLoc?.type === 'intron') {
114
- fivePrimeSpliceSite = refData.getSequence(min - 2, min)
115
- }
116
- if (nextLoc?.type === 'intron') {
117
- threePrimeSpliceSite = refData.getSequence(max, max + 2)
118
- }
119
- } else {
120
- if (previousLoc?.type === 'intron') {
121
- fivePrimeSpliceSite = revcom(refData.getSequence(max, max + 2))
122
- }
123
- if (nextLoc?.type === 'intron') {
124
- threePrimeSpliceSite = revcom(refData.getSequence(min - 2, min))
125
- }
126
- }
127
- }
128
- return {
129
- min,
130
- max,
131
- label,
132
- fivePrimeSpliceSite,
133
- threePrimeSpliceSite,
134
- frameColor,
135
- }
136
- })
137
- .filter((loc) => loc.label !== 'intron')
138
-
139
- return (
140
- <>
141
- <Typography variant="h5">Structure</Typography>
142
- <Typography variant="h6">
143
- {strand === 1 ? 'Forward' : 'Reverse'} strand
144
- </Typography>
145
- <TableContainer component={Paper}>
146
- <Table size="small">
147
- <TableBody>
148
- {locationData.map((loc) => (
149
- <TableRow key={`${loc.label}:${loc.min}-${loc.max}`}>
150
- <TableCell
151
- component="th"
152
- scope="row"
153
- style={{ background: loc.frameColor }}
154
- >
155
- {loc.label}
156
- </TableCell>
157
- <TableCell>{loc.fivePrimeSpliceSite ?? ''}</TableCell>
158
- <TableCell padding="none">
159
- <NumberTextField
160
- margin="dense"
161
- variant="outlined"
162
- value={strand === 1 ? loc.min + 1 : loc.max}
163
- onChangeCommitted={(newLocation: number) => {
164
- handleLocationChange(
165
- strand === 1 ? loc.min + 1 : loc.max,
166
- newLocation,
167
- feature,
168
- strand === 1,
169
- )
170
- }}
171
- />
172
- {/* {strand === 1 ? loc.min : loc.max} */}
173
- </TableCell>
174
- <TableCell padding="none">
175
- <NumberTextField
176
- margin="dense"
177
- // disabled={item.type !== 'CDS'}
178
- variant="outlined"
179
- value={strand === 1 ? loc.max : loc.min + 1}
180
- onChangeCommitted={(newLocation: number) => {
181
- handleLocationChange(
182
- strand === 1 ? loc.max : loc.min + 1,
183
- newLocation,
184
- feature,
185
- strand !== 1,
186
- )
187
- }}
188
- />
189
- {/* {strand === 1 ? loc.max : loc.min} */}
190
- </TableCell>
191
- <TableCell>{loc.threePrimeSpliceSite ?? ''}</TableCell>
192
- </TableRow>
193
- ))}
194
- </TableBody>
195
- </Table>
196
- </TableContainer>
197
- </>
198
- )
199
- },
200
- )
@@ -1,19 +0,0 @@
1
- import { observer } from 'mobx-react'
2
- import React from 'react'
3
-
4
- import { SixFrameFeatureDisplay } from '../stateModel'
5
-
6
- export const TrackLines = observer(function TrackLines({
7
- model,
8
- }: {
9
- model: SixFrameFeatureDisplay
10
- }) {
11
- const { height } = model
12
- return (
13
- <div
14
- style={{ position: 'absolute', left: 0, top: height / 2, width: '100%' }}
15
- >
16
- <hr style={{ margin: 0, top: 0, color: 'black' }} />
17
- </div>
18
- )
19
- })
@@ -1 +0,0 @@
1
- export * from './TrackLines'
@@ -1,21 +0,0 @@
1
- import { ConfigurationSchema } from '@jbrowse/core/configuration'
2
- import PluginManager from '@jbrowse/core/PluginManager'
3
- import type LinearGenomeViewPlugin from '@jbrowse/plugin-linear-genome-view'
4
-
5
- import { configSchema as apolloRendererConfigSchema } from '../ApolloSixFrameRenderer'
6
-
7
- export function configSchemaFactory(pluginManager: PluginManager) {
8
- const LGVPlugin = pluginManager.getPlugin(
9
- 'LinearGenomeViewPlugin',
10
- ) as LinearGenomeViewPlugin
11
- const { baseLinearDisplayConfigSchema } = LGVPlugin.exports
12
-
13
- return ConfigurationSchema(
14
- 'SixFrameFeatureDisplay',
15
- {
16
- renderer: apolloRendererConfigSchema,
17
- height: { type: 'number', defaultValue: 120 },
18
- },
19
- { baseConfiguration: baseLinearDisplayConfigSchema, explicitlyTyped: true },
20
- )
21
- }
@@ -1,2 +0,0 @@
1
- export { configSchemaFactory } from './configSchema'
2
- export { stateModelFactory } from './stateModel'
@@ -1,439 +0,0 @@
1
- /* eslint-disable @typescript-eslint/restrict-plus-operands */
2
- /* eslint-disable @typescript-eslint/no-unsafe-return */
3
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
- /* eslint-disable @typescript-eslint/no-unnecessary-condition */
5
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
6
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
7
- /* eslint-disable @typescript-eslint/unbound-method */
8
- import { AnnotationFeature } from '@apollo-annotation/mst'
9
- import { ConfigurationReference } from '@jbrowse/core/configuration'
10
- import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
11
- import PluginManager from '@jbrowse/core/PluginManager'
12
- import {
13
- defaultStarts,
14
- defaultStops,
15
- getContainingView,
16
- getSession,
17
- revcom,
18
- reverse,
19
- } from '@jbrowse/core/util'
20
- import { BaseBlock } from '@jbrowse/core/util/blockTypes'
21
- import { getParentRenderProps } from '@jbrowse/core/util/tracks'
22
- import type LinearGenomeViewPlugin from '@jbrowse/plugin-linear-genome-view'
23
- import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
24
- import { autorun } from 'mobx'
25
- import { Instance, addDisposer, types } from 'mobx-state-tree'
26
-
27
- import { ApolloSession, ApolloSessionModel } from '../session'
28
-
29
- const forwardPhaseMap: Record<number, number> = { 0: 2, 1: 1, 2: 0 }
30
- const reversePhaseMap: Record<number, number> = { 3: 0, 4: 1, 5: 2 }
31
-
32
- export function stateModelFactory(
33
- pluginManager: PluginManager,
34
- configSchema: AnyConfigurationSchemaType,
35
- ) {
36
- const LGVPlugin = pluginManager.getPlugin(
37
- 'LinearGenomeViewPlugin',
38
- ) as LinearGenomeViewPlugin
39
- const { BaseLinearDisplay } = LGVPlugin.exports
40
-
41
- return BaseLinearDisplay.named('SixFrameFeatureDisplay')
42
- .props({
43
- type: types.literal('SixFrameFeatureDisplay'),
44
- configuration: ConfigurationReference(configSchema),
45
- apolloRowHeight: 20,
46
- detailsMinHeight: 200,
47
- showStartCodons: false,
48
- showStopCodons: true,
49
- showIntronLines: true,
50
- })
51
- .volatile(() => ({
52
- apolloFeatureUnderMouse: undefined as AnnotationFeature | undefined,
53
- apolloRowUnderMouse: undefined as number | undefined,
54
- }))
55
- .views((self) => {
56
- const { configuration, renderProps: superRenderProps } = self
57
- return {
58
- renderProps() {
59
- return {
60
- ...superRenderProps(),
61
- ...getParentRenderProps(self),
62
- config: configuration.renderer,
63
- }
64
- },
65
- }
66
- })
67
- .views((self) => ({
68
- get regions() {
69
- let blockDefinitions
70
- try {
71
- ;({ blockDefinitions } = self)
72
- } catch {
73
- return []
74
- }
75
- const regions = blockDefinitions.contentBlocks.map(
76
- ({ assemblyName, end, refName, start }) => ({
77
- assemblyName,
78
- refName,
79
- start,
80
- end,
81
- }),
82
- )
83
- return regions
84
- },
85
- regionCannotBeRendered(/* region */) {
86
- const view = getContainingView(self) as unknown as LinearGenomeViewModel
87
- if (view && view.bpPerPx >= 200) {
88
- return 'Zoom in to see annotations'
89
- }
90
- return
91
- },
92
- get session() {
93
- return getSession(self) as unknown as ApolloSessionModel
94
- },
95
- }))
96
- .actions((self) => {
97
- let previousBlockKeys: string[] = []
98
- return {
99
- afterAttach() {
100
- addDisposer(
101
- self,
102
- autorun(
103
- () => {
104
- const session = getSession(self) as ApolloSession
105
- const view = getContainingView(
106
- self,
107
- ) as unknown as LinearGenomeViewModel
108
- if (view.initialized) {
109
- if (self.regionCannotBeRendered()) {
110
- return
111
- }
112
- const blockKeys: string[] = []
113
- const newBlocks: BaseBlock[] = []
114
- for (const block of self.blockDefinitions.contentBlocks) {
115
- blockKeys.push(block.key)
116
- if (!previousBlockKeys.includes(block.key)) {
117
- newBlocks.push(block)
118
- }
119
- }
120
- session.apolloDataStore.loadFeatures(
121
- newBlocks.map(({ assemblyName, end, refName, start }) => ({
122
- assemblyName,
123
- refName,
124
- start,
125
- end,
126
- })),
127
- )
128
- session.apolloDataStore.loadRefSeq(
129
- newBlocks.map(({ assemblyName, end, refName, start }) => ({
130
- assemblyName,
131
- refName,
132
- start,
133
- end,
134
- })),
135
- )
136
- previousBlockKeys = blockKeys
137
- }
138
- },
139
- { name: 'SixFrameFeatureDisplay' },
140
- ),
141
- )
142
- },
143
- }
144
- })
145
- .views((self) => ({
146
- get rendererTypeName() {
147
- return self.configuration.renderer.type
148
- },
149
- get changeManager() {
150
- const session = getSession(self) as ApolloSession
151
- return session.apolloDataStore.changeManager
152
- },
153
- get sequence() {
154
- const { regions } = self
155
- const session = getSession(self) as ApolloSession
156
- const seq = new Map<number, string>()
157
- for (const region of regions) {
158
- const assembly = session.apolloDataStore.assemblies.get(
159
- region.assemblyName,
160
- )
161
- const ref = assembly?.getByRefName(region.refName)
162
- const refSeq: string | undefined = ref?.getSequence(
163
- region.start,
164
- region.end,
165
- )
166
- seq.set(region.start, refSeq ?? '')
167
- }
168
- return seq
169
- },
170
- get features() {
171
- const { regions } = self
172
- const session = getSession(self) as ApolloSession
173
- const features = new Map<string, Map<string, AnnotationFeature>>()
174
- for (const region of regions) {
175
- const assembly = session.apolloDataStore.assemblies.get(
176
- region.assemblyName,
177
- )
178
- const ref = assembly?.getByRefName(region.refName)
179
- let filteredRef = features.get(region.refName)
180
- if (!filteredRef) {
181
- filteredRef = new Map<string, AnnotationFeature>()
182
- features.set(region.refName, filteredRef)
183
- }
184
- for (const [featureId, feature] of ref?.features.entries() ??
185
- new Map()) {
186
- if (region.start < feature.end && region.end > feature.start) {
187
- filteredRef.set(featureId, feature)
188
- }
189
- }
190
- }
191
- return features
192
- },
193
- get featuresMinMax() {
194
- const minMax: Record<string, [number, number]> = {}
195
- for (const [refSeq, featuresForRefSeq] of this.features || []) {
196
- let min: number | undefined
197
- let max: number | undefined
198
- for (const [, featureLocation] of featuresForRefSeq) {
199
- if (min === undefined) {
200
- ;({ min } = featureLocation)
201
- }
202
- if (max === undefined) {
203
- ;({ max } = featureLocation)
204
- }
205
- if (featureLocation.min < min) {
206
- ;({ min } = featureLocation)
207
- }
208
- if (featureLocation.max > max) {
209
- ;({ max } = featureLocation)
210
- }
211
- }
212
- if (min !== undefined && max !== undefined) {
213
- minMax[refSeq] = [min, max]
214
- }
215
- }
216
- return minMax
217
- },
218
- get codonLayout() {
219
- const codonLayout = new Map<
220
- number,
221
- { starts: number[]; stops: number[] }
222
- >()
223
- let fullSeq = ''
224
- let fullStart = 0
225
- for (const [regionStart, seq] of this.sequence || []) {
226
- if (!seq) {
227
- continue
228
- }
229
- if (!fullSeq) {
230
- fullStart = regionStart
231
- }
232
- fullSeq += seq
233
- }
234
- const rowCount = 6
235
- for (let i = 0; i < rowCount; i++) {
236
- const starts: number[] = []
237
- const stops: number[] = []
238
- const reversed = i in reversePhaseMap
239
- // the tilt variable normalizes the frame to where we are starting from,
240
- // which increases consistency across blocks
241
- let tilt
242
- // the effectiveFrame incorporates tilt and the frame to say what the
243
- // effective frame that is plotted. The +3 is for when frame is -2 and this
244
- // can otherwise result in effectiveFrame -1
245
- let effectiveFrame
246
- let seqSliced
247
- if (reversed) {
248
- tilt = (fullSeq.length + fullStart) % 3
249
- effectiveFrame = (reversePhaseMap[i] + tilt + 3) % 3
250
- seqSliced = reverse(fullSeq).slice(effectiveFrame)
251
- } else {
252
- tilt = 3 - (fullStart % 3)
253
- effectiveFrame = (forwardPhaseMap[i] + tilt + 3) % 3
254
- seqSliced = fullSeq.slice(effectiveFrame)
255
- }
256
- for (let j = 0; j < seqSliced.length; j += 3) {
257
- const codon = seqSliced.slice(j, j + 3)
258
- const normalizedCodon = reversed ? reverse(revcom(codon)) : codon
259
- const start = reversed
260
- ? fullStart + seqSliced.length - (3 + j)
261
- : fullStart + j + effectiveFrame
262
- if (defaultStarts.includes(normalizedCodon.toUpperCase())) {
263
- starts.push(start)
264
- } else if (defaultStops.includes(normalizedCodon.toUpperCase())) {
265
- stops.push(start)
266
- }
267
- }
268
- codonLayout.set(i, { starts, stops })
269
- }
270
- return codonLayout
271
- },
272
- get featureLayout() {
273
- const { featureTypeOntology } =
274
- self.session.apolloDataStore.ontologyManager
275
- if (!featureTypeOntology) {
276
- throw new Error('featureTypeOntology is undefined')
277
- }
278
- const featureLayout = new Map<number, [string, AnnotationFeature][]>()
279
- for (const [refSeq, featuresForRefSeq] of this.features || []) {
280
- if (!featuresForRefSeq) {
281
- continue
282
- }
283
- const minMaxfeatures = this.featuresMinMax[refSeq]
284
- if (!minMaxfeatures) {
285
- continue
286
- }
287
- const [min, max] = minMaxfeatures
288
- const rows: boolean[][] = []
289
- const rowCount = 6
290
- for (let i = 0; i < rowCount; i++) {
291
- const newRowNumber = rows.length
292
- rows[newRowNumber] = Array.from({ length: max - min })
293
- featureLayout.set(newRowNumber, [])
294
- }
295
- for (const feature of [...featuresForRefSeq.values()].sort(
296
- (f1, f2) => {
297
- const { max: end1, min: start1 } = f1
298
- const { max: end2, min: start2 } = f2
299
- return start1 - start2 || end1 - end2
300
- },
301
- )) {
302
- for (const [, childFeature] of feature.children ?? new Map()) {
303
- if (
304
- featureTypeOntology.isTypeOf(childFeature.type, 'transcript')
305
- ) {
306
- for (const [, grandChildFeature] of childFeature.children ||
307
- new Map()) {
308
- let startingRow
309
- if (
310
- featureTypeOntology.isTypeOf(grandChildFeature.type, 'CDS')
311
- ) {
312
- let discontinuousLocations
313
- if (grandChildFeature.discontinuousLocations.length > 0) {
314
- ;({ discontinuousLocations } = grandChildFeature)
315
- } else {
316
- discontinuousLocations = [grandChildFeature]
317
- }
318
- for (const cds of discontinuousLocations) {
319
- const min = cds.start + 3
320
- const max = cds.end - 3
321
- // Remove codons either end of feature when considering intersect.
322
- for (const [row, { stops }] of this.codonLayout) {
323
- if (
324
- (row < 3 && feature.strand === 1) ||
325
- (row >= 3 && feature.strand === -1)
326
- ) {
327
- const filteredArray = stops.filter(
328
- (value) => value >= min && value <= max,
329
- )
330
- if (filteredArray.length === 0) {
331
- startingRow = row
332
- const layoutRow = featureLayout.get(startingRow)
333
- layoutRow?.push([childFeature.featureId, cds])
334
- break
335
- }
336
- }
337
- }
338
- }
339
- }
340
- }
341
- }
342
- }
343
- }
344
- }
345
- return featureLayout
346
- },
347
- getAssemblyId(assemblyName: string) {
348
- const { assemblyManager } = getSession(self)
349
- const assembly = assemblyManager.get(assemblyName)
350
- if (!assembly) {
351
- throw new Error(`Could not find assembly named ${assemblyName}`)
352
- }
353
- return assembly.name
354
- },
355
- get selectedFeature(): AnnotationFeature | undefined {
356
- const session = getSession(self) as ApolloSession
357
- return session.apolloSelectedFeature
358
- },
359
- get setSelectedFeature() {
360
- const session = getSession(self) as ApolloSession
361
- return session.apolloSetSelectedFeature
362
- },
363
- }))
364
- .actions((self) => ({
365
- setSelectedFeature(feature?: AnnotationFeature) {
366
- const session = getSession(self) as ApolloSession
367
- session.apolloSetSelectedFeature(feature)
368
- },
369
- setApolloFeatureUnderMouse(feature?: AnnotationFeature) {
370
- self.apolloFeatureUnderMouse = feature
371
- },
372
- setApolloRowUnderMouse(row?: number) {
373
- self.apolloRowUnderMouse = row
374
- },
375
- toggleShowStartCodons() {
376
- self.showStartCodons = !self.showStartCodons
377
- },
378
- toggleShowStopCodons() {
379
- self.showStopCodons = !self.showStopCodons
380
- },
381
- toggleShowIntronLines() {
382
- self.showIntronLines = !self.showIntronLines
383
- },
384
- }))
385
- .views((self) => ({
386
- get highestRow() {
387
- if (self.featureLayout.size === 0) {
388
- return 0
389
- }
390
- return Math.max(...self.featureLayout.keys())
391
- },
392
- get featuresHeight() {
393
- return (this.highestRow + 1) * self.apolloRowHeight
394
- },
395
- get detailsHeight() {
396
- return Math.max(
397
- self.detailsMinHeight,
398
- self.height - this.featuresHeight,
399
- )
400
- },
401
- trackMenuItems() {
402
- return [
403
- {
404
- label: 'Show start codons',
405
- type: 'checkbox',
406
- checked: self.showStartCodons,
407
- onClick: () => {
408
- self.toggleShowStartCodons()
409
- },
410
- },
411
- {
412
- label: 'Show stop codons',
413
- type: 'checkbox',
414
- checked: self.showStopCodons,
415
- onClick: () => {
416
- self.toggleShowStopCodons()
417
- },
418
- },
419
- {
420
- label: 'Show intron lines',
421
- type: 'checkbox',
422
- checked: self.showIntronLines,
423
- onClick: () => {
424
- self.toggleShowIntronLines()
425
- },
426
- },
427
- ]
428
- },
429
- }))
430
- }
431
-
432
- export type SixFrameFeatureDisplayStateModel = ReturnType<
433
- typeof stateModelFactory
434
- >
435
- // eslint disable because of
436
- // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
437
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
438
- export interface SixFrameFeatureDisplay
439
- extends Instance<SixFrameFeatureDisplayStateModel> {}