@apollo-annotation/jbrowse-plugin-apollo 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +6964 -4598
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +6610 -4261
- package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.development.js +11563 -7493
- package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
- package/package.json +4 -4
- package/src/ApolloInternetAccount/addMenuItems.ts +23 -2
- package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
- package/src/ApolloInternetAccount/components/LoginButtons.tsx +1 -1
- package/src/ApolloInternetAccount/components/LoginIcons.tsx +1 -1
- package/src/ApolloInternetAccount/configSchema.ts +1 -1
- package/src/ApolloInternetAccount/model.ts +11 -10
- package/src/ApolloJobModel.ts +1 -1
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +8 -6
- package/src/ApolloRefNameAliasAdapter/index.ts +2 -2
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +4 -4
- package/src/ApolloSequenceAdapter/index.ts +1 -1
- package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +8 -7
- package/src/ApolloTextSearchAdapter/index.ts +1 -1
- package/src/BackendDrivers/BackendDriver.ts +7 -7
- package/src/BackendDrivers/CollaborationServerDriver.ts +14 -10
- package/src/BackendDrivers/DesktopFileDriver.ts +11 -10
- package/src/BackendDrivers/InMemoryFileDriver.ts +10 -6
- package/src/ChangeManager.ts +15 -11
- package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +8 -7
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +35 -14
- package/src/FeatureDetailsWidget/AttributeKey.tsx +50 -0
- package/src/FeatureDetailsWidget/AttributeKeySelector.tsx +104 -0
- package/src/FeatureDetailsWidget/Attributes.tsx +215 -367
- package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -5
- package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +104 -0
- package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +22 -0
- package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +4 -4
- package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -1
- package/src/FeatureDetailsWidget/Sequence.tsx +2 -2
- package/src/FeatureDetailsWidget/StringTextField.tsx +1 -1
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +15 -23
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +950 -196
- package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +8 -4
- package/src/FeatureDetailsWidget/model.ts +8 -3
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +7 -7
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +59 -72
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +253 -60
- package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +52 -6
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +16 -8
- package/src/LinearApolloDisplay/stateModel/base.ts +81 -10
- package/src/LinearApolloDisplay/stateModel/index.ts +4 -3
- package/src/LinearApolloDisplay/stateModel/layouts.ts +8 -39
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +63 -46
- package/src/LinearApolloDisplay/stateModel/rendering.ts +60 -31
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +226 -0
- package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +32 -0
- package/src/LinearApolloSixFrameDisplay/components/index.ts +2 -0
- package/src/LinearApolloSixFrameDisplay/configSchema.ts +7 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +940 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +63 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/index.ts +1 -0
- package/src/LinearApolloSixFrameDisplay/index.ts +2 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +302 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/index.ts +27 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +252 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +368 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +201 -0
- package/src/LinearApolloSixFrameDisplay/types.ts +1 -0
- package/src/OntologyManager/OntologyStore/fulltext.test.ts +1 -1
- package/src/OntologyManager/OntologyStore/fulltext.ts +8 -3
- package/src/OntologyManager/OntologyStore/index.test.ts +3 -1
- package/src/OntologyManager/OntologyStore/index.ts +19 -14
- package/src/OntologyManager/OntologyStore/indexeddb-schema.ts +6 -5
- package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +11 -5
- package/src/OntologyManager/index.ts +12 -7
- package/src/OntologyManager/util.ts +3 -2
- package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
- package/src/TabularEditor/HybridGrid/Feature.tsx +13 -7
- package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +1 -1
- package/src/TabularEditor/HybridGrid/HybridGrid.tsx +3 -2
- package/src/TabularEditor/HybridGrid/ToolBar.tsx +1 -1
- package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +114 -22
- package/src/TabularEditor/TabularEditorPane.tsx +1 -1
- package/src/TabularEditor/model.ts +2 -2
- package/src/TabularEditor/types.ts +5 -2
- package/src/components/AddAssembly.tsx +182 -179
- package/src/components/AddAssemblyAliases.tsx +114 -0
- package/src/components/AddChildFeature.tsx +8 -10
- package/src/components/AddFeature.tsx +216 -44
- package/src/components/AddRefSeqAliases.tsx +14 -12
- package/src/components/CopyFeature.tsx +10 -11
- package/src/components/CreateApolloAnnotation.tsx +342 -158
- package/src/components/DeleteAssembly.tsx +9 -8
- package/src/components/DeleteFeature.tsx +362 -14
- package/src/components/Dialog.tsx +1 -1
- package/src/components/DownloadGFF3.tsx +31 -11
- package/src/components/FilterFeatures.tsx +6 -4
- package/src/components/FilterTranscripts.tsx +86 -0
- package/src/components/ImportFeatures.tsx +7 -6
- package/src/components/LogOut.tsx +5 -4
- package/src/components/ManageChecks.tsx +9 -8
- package/src/components/ManageUsers.tsx +11 -10
- package/src/components/MergeExons.tsx +193 -0
- package/src/components/MergeTranscripts.tsx +185 -0
- package/src/components/OntologyTermAutocomplete.tsx +5 -5
- package/src/components/OntologyTermMultiSelect.tsx +6 -6
- package/src/components/OpenLocalFile.tsx +4 -3
- package/src/components/SplitExon.tsx +134 -0
- package/src/components/ViewChangeLog.tsx +7 -6
- package/src/components/ViewCheckResults.tsx +8 -7
- package/src/components/index.ts +3 -0
- package/src/config.ts +5 -0
- package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -0
- package/src/extensions/annotationFromJBrowseFeature.ts +13 -10
- package/src/extensions/annotationFromPileup.ts +104 -94
- package/src/index.ts +33 -50
- package/src/makeDisplayComponent.tsx +90 -37
- package/src/session/ClientDataStore.ts +21 -17
- package/src/session/session.ts +46 -39
- package/src/types.ts +4 -4
- package/src/util/annotationFeatureUtils.ts +66 -1
- package/src/util/copyToClipboard.ts +21 -0
- package/src/util/glyphUtils.ts +49 -0
- package/src/util/index.ts +5 -3
- package/src/util/loadAssemblyIntoClient.ts +10 -3
- package/src/util/mouseEventsUtils.ts +113 -0
- package/src/ApolloSixFrameRenderer/ApolloSixFrameRenderer.tsx +0 -13
- package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +0 -707
- package/src/ApolloSixFrameRenderer/configSchema.ts +0 -7
- package/src/ApolloSixFrameRenderer/index.ts +0 -3
- package/src/SixFrameFeatureDisplay/components/TrackLines.tsx +0 -19
- package/src/SixFrameFeatureDisplay/components/index.ts +0 -1
- package/src/SixFrameFeatureDisplay/configSchema.ts +0 -21
- package/src/SixFrameFeatureDisplay/index.ts +0 -2
- package/src/SixFrameFeatureDisplay/stateModel.ts +0 -443
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type AnnotationFeature } from '@apollo-annotation/mst'
|
|
2
|
+
import { type MenuItem } from '@jbrowse/core/ui'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type LinearApolloSixFrameDisplayMouseEvents,
|
|
6
|
+
type MousePositionWithFeatureAndGlyph,
|
|
7
|
+
} from '../stateModel/mouseEvents'
|
|
8
|
+
import { type LinearApolloSixFrameDisplayRendering } from '../stateModel/rendering'
|
|
9
|
+
import { type CanvasMouseEvent } from '../types'
|
|
10
|
+
|
|
11
|
+
export interface Glyph {
|
|
12
|
+
/** draw the feature's primary rendering on the canvas */
|
|
13
|
+
draw(
|
|
14
|
+
ctx: CanvasRenderingContext2D,
|
|
15
|
+
feature: AnnotationFeature,
|
|
16
|
+
row: number,
|
|
17
|
+
stateModel: LinearApolloSixFrameDisplayRendering,
|
|
18
|
+
displayedRegionIndex: number,
|
|
19
|
+
): void
|
|
20
|
+
|
|
21
|
+
drawHover(
|
|
22
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
23
|
+
overlayCtx: CanvasRenderingContext2D,
|
|
24
|
+
): void
|
|
25
|
+
|
|
26
|
+
drawDragPreview(
|
|
27
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
28
|
+
ctx: CanvasRenderingContext2D,
|
|
29
|
+
): void
|
|
30
|
+
|
|
31
|
+
onMouseDown(
|
|
32
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
33
|
+
currentMousePosition: MousePositionWithFeatureAndGlyph,
|
|
34
|
+
event: CanvasMouseEvent,
|
|
35
|
+
): void
|
|
36
|
+
|
|
37
|
+
onMouseMove(
|
|
38
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
39
|
+
currentMousePosition: MousePositionWithFeatureAndGlyph,
|
|
40
|
+
event: CanvasMouseEvent,
|
|
41
|
+
): void
|
|
42
|
+
|
|
43
|
+
onMouseLeave(
|
|
44
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
45
|
+
currentMousePosition: MousePositionWithFeatureAndGlyph,
|
|
46
|
+
event: CanvasMouseEvent,
|
|
47
|
+
): void
|
|
48
|
+
|
|
49
|
+
onMouseUp(
|
|
50
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
51
|
+
currentMousePosition: MousePositionWithFeatureAndGlyph,
|
|
52
|
+
event: CanvasMouseEvent,
|
|
53
|
+
): void
|
|
54
|
+
|
|
55
|
+
drawTooltip(
|
|
56
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
57
|
+
context: CanvasRenderingContext2D,
|
|
58
|
+
): void
|
|
59
|
+
|
|
60
|
+
getContextMenuItems(
|
|
61
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
62
|
+
): MenuItem[]
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './GeneGlyph'
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
6
|
+
import { type AnnotationFeature } from '@apollo-annotation/mst'
|
|
7
|
+
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
8
|
+
import { ConfigurationReference, getConf } from '@jbrowse/core/configuration'
|
|
9
|
+
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
10
|
+
import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes'
|
|
11
|
+
import {
|
|
12
|
+
type AbstractSessionModel,
|
|
13
|
+
type SessionWithWidgets,
|
|
14
|
+
getContainingView,
|
|
15
|
+
getSession,
|
|
16
|
+
} from '@jbrowse/core/util'
|
|
17
|
+
import { getParentRenderProps } from '@jbrowse/core/util/tracks'
|
|
18
|
+
// import type LinearGenomeViewPlugin from '@jbrowse/plugin-linear-genome-view'
|
|
19
|
+
import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
20
|
+
import { autorun } from 'mobx'
|
|
21
|
+
import { addDisposer, cast, getRoot, getSnapshot, types } from 'mobx-state-tree'
|
|
22
|
+
|
|
23
|
+
import { type ApolloInternetAccountModel } from '../../ApolloInternetAccount/model'
|
|
24
|
+
import { FilterFeatures } from '../../components/FilterFeatures'
|
|
25
|
+
import { type ApolloSessionModel } from '../../session'
|
|
26
|
+
import { type ApolloRootModel } from '../../types'
|
|
27
|
+
|
|
28
|
+
const minDisplayHeight = 20
|
|
29
|
+
|
|
30
|
+
export function baseModelFactory(
|
|
31
|
+
_pluginManager: PluginManager,
|
|
32
|
+
configSchema: AnyConfigurationSchemaType,
|
|
33
|
+
) {
|
|
34
|
+
return BaseDisplay.named('BaseLinearApolloSixFrameDisplay')
|
|
35
|
+
.props({
|
|
36
|
+
type: types.literal('LinearApolloSixFrameDisplay'),
|
|
37
|
+
configuration: ConfigurationReference(configSchema),
|
|
38
|
+
graphical: true,
|
|
39
|
+
table: false,
|
|
40
|
+
showFeatureLabels: true,
|
|
41
|
+
heightPreConfig: types.maybe(
|
|
42
|
+
types.refinement(
|
|
43
|
+
'displayHeight',
|
|
44
|
+
types.number,
|
|
45
|
+
(n) => n >= minDisplayHeight,
|
|
46
|
+
),
|
|
47
|
+
),
|
|
48
|
+
filteredFeatureTypes: types.array(types.string),
|
|
49
|
+
})
|
|
50
|
+
.views((self) => {
|
|
51
|
+
const { configuration, renderProps: superRenderProps } = self
|
|
52
|
+
return {
|
|
53
|
+
renderProps() {
|
|
54
|
+
return {
|
|
55
|
+
...superRenderProps(),
|
|
56
|
+
...getParentRenderProps(self),
|
|
57
|
+
config: configuration.renderer,
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
.volatile(() => ({
|
|
63
|
+
scrollTop: 0,
|
|
64
|
+
}))
|
|
65
|
+
.views((self) => ({
|
|
66
|
+
get lgv() {
|
|
67
|
+
return getContainingView(self) as unknown as LinearGenomeViewModel
|
|
68
|
+
},
|
|
69
|
+
get height() {
|
|
70
|
+
if (self.heightPreConfig) {
|
|
71
|
+
return self.heightPreConfig
|
|
72
|
+
}
|
|
73
|
+
if (self.graphical && self.table) {
|
|
74
|
+
return 500
|
|
75
|
+
}
|
|
76
|
+
if (self.graphical) {
|
|
77
|
+
return 200
|
|
78
|
+
}
|
|
79
|
+
return 300
|
|
80
|
+
},
|
|
81
|
+
}))
|
|
82
|
+
.views((self) => ({
|
|
83
|
+
get rendererTypeName() {
|
|
84
|
+
return self.configuration.renderer.type
|
|
85
|
+
},
|
|
86
|
+
get session() {
|
|
87
|
+
return getSession(self) as unknown as ApolloSessionModel
|
|
88
|
+
},
|
|
89
|
+
get regions() {
|
|
90
|
+
const regions = self.lgv.dynamicBlocks.contentBlocks.map(
|
|
91
|
+
({ assemblyName, end, refName, start }) => ({
|
|
92
|
+
assemblyName,
|
|
93
|
+
refName,
|
|
94
|
+
start: Math.round(start),
|
|
95
|
+
end: Math.round(end),
|
|
96
|
+
}),
|
|
97
|
+
)
|
|
98
|
+
return regions
|
|
99
|
+
},
|
|
100
|
+
regionCannotBeRendered(/* region */) {
|
|
101
|
+
if (self.lgv && self.lgv.bpPerPx >= 200) {
|
|
102
|
+
return 'Zoom in to see annotations'
|
|
103
|
+
}
|
|
104
|
+
return
|
|
105
|
+
},
|
|
106
|
+
}))
|
|
107
|
+
.views((self) => ({
|
|
108
|
+
get apolloInternetAccount() {
|
|
109
|
+
const [region] = self.regions
|
|
110
|
+
const { internetAccounts } = getRoot<ApolloRootModel>(self)
|
|
111
|
+
const { assemblyName } = region
|
|
112
|
+
const { assemblyManager } =
|
|
113
|
+
self.session as unknown as AbstractSessionModel
|
|
114
|
+
const assembly = assemblyManager.get(assemblyName)
|
|
115
|
+
if (!assembly) {
|
|
116
|
+
throw new Error(`No assembly found with name ${assemblyName}`)
|
|
117
|
+
}
|
|
118
|
+
const { internetAccountConfigId } = getConf(assembly, [
|
|
119
|
+
'sequence',
|
|
120
|
+
'metadata',
|
|
121
|
+
]) as { internetAccountConfigId: string }
|
|
122
|
+
return internetAccounts.find(
|
|
123
|
+
(ia) => getConf(ia, 'internetAccountId') === internetAccountConfigId,
|
|
124
|
+
) as ApolloInternetAccountModel | undefined
|
|
125
|
+
},
|
|
126
|
+
get changeManager() {
|
|
127
|
+
return (self.session as unknown as ApolloSessionModel).apolloDataStore
|
|
128
|
+
.changeManager
|
|
129
|
+
},
|
|
130
|
+
getAssemblyId(assemblyName: string) {
|
|
131
|
+
const { assemblyManager } =
|
|
132
|
+
self.session as unknown as AbstractSessionModel
|
|
133
|
+
const assembly = assemblyManager.get(assemblyName)
|
|
134
|
+
if (!assembly) {
|
|
135
|
+
throw new Error(`Could not find assembly named ${assemblyName}`)
|
|
136
|
+
}
|
|
137
|
+
return assembly.name
|
|
138
|
+
},
|
|
139
|
+
get selectedFeature(): AnnotationFeature | undefined {
|
|
140
|
+
return (self.session as unknown as ApolloSessionModel)
|
|
141
|
+
.apolloSelectedFeature
|
|
142
|
+
},
|
|
143
|
+
}))
|
|
144
|
+
.actions((self) => ({
|
|
145
|
+
setScrollTop(scrollTop: number) {
|
|
146
|
+
self.scrollTop = scrollTop
|
|
147
|
+
},
|
|
148
|
+
setHeight(displayHeight: number) {
|
|
149
|
+
self.heightPreConfig = Math.max(displayHeight, minDisplayHeight)
|
|
150
|
+
return self.height
|
|
151
|
+
},
|
|
152
|
+
resizeHeight(distance: number) {
|
|
153
|
+
const oldHeight = self.height
|
|
154
|
+
const newHeight = this.setHeight(self.height + distance)
|
|
155
|
+
return newHeight - oldHeight
|
|
156
|
+
},
|
|
157
|
+
showGraphicalOnly() {
|
|
158
|
+
self.graphical = true
|
|
159
|
+
self.table = false
|
|
160
|
+
},
|
|
161
|
+
showTableOnly() {
|
|
162
|
+
self.graphical = false
|
|
163
|
+
self.table = true
|
|
164
|
+
},
|
|
165
|
+
showGraphicalAndTable() {
|
|
166
|
+
self.graphical = true
|
|
167
|
+
self.table = true
|
|
168
|
+
},
|
|
169
|
+
toggleShowFeatureLabels() {
|
|
170
|
+
self.showFeatureLabels = !self.showFeatureLabels
|
|
171
|
+
},
|
|
172
|
+
updateFilteredFeatureTypes(types: string[]) {
|
|
173
|
+
self.filteredFeatureTypes = cast(types)
|
|
174
|
+
},
|
|
175
|
+
}))
|
|
176
|
+
.views((self) => {
|
|
177
|
+
const { filteredFeatureTypes, trackMenuItems: superTrackMenuItems } = self
|
|
178
|
+
return {
|
|
179
|
+
trackMenuItems() {
|
|
180
|
+
const { graphical, table, showFeatureLabels } = self
|
|
181
|
+
return [
|
|
182
|
+
...superTrackMenuItems(),
|
|
183
|
+
{
|
|
184
|
+
type: 'subMenu',
|
|
185
|
+
label: 'Appearance',
|
|
186
|
+
subMenu: [
|
|
187
|
+
{
|
|
188
|
+
label: 'Show graphical display',
|
|
189
|
+
type: 'radio',
|
|
190
|
+
checked: graphical && !table,
|
|
191
|
+
onClick: () => {
|
|
192
|
+
self.showGraphicalOnly()
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
label: 'Show table display',
|
|
197
|
+
type: 'radio',
|
|
198
|
+
checked: table && !graphical,
|
|
199
|
+
onClick: () => {
|
|
200
|
+
self.showTableOnly()
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
label: 'Show both graphical and table display',
|
|
205
|
+
type: 'radio',
|
|
206
|
+
checked: table && graphical,
|
|
207
|
+
onClick: () => {
|
|
208
|
+
self.showGraphicalAndTable()
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
label: 'Feature Labels',
|
|
213
|
+
type: 'checkbox',
|
|
214
|
+
checked: showFeatureLabels,
|
|
215
|
+
onClick: () => {
|
|
216
|
+
self.toggleShowFeatureLabels()
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
label: 'Filter features by type',
|
|
223
|
+
onClick: () => {
|
|
224
|
+
const session = self.session as unknown as ApolloSessionModel
|
|
225
|
+
;(self.session as unknown as AbstractSessionModel).queueDialog(
|
|
226
|
+
(doneCallback) => [
|
|
227
|
+
FilterFeatures,
|
|
228
|
+
{
|
|
229
|
+
session,
|
|
230
|
+
handleClose: () => {
|
|
231
|
+
doneCallback()
|
|
232
|
+
},
|
|
233
|
+
featureTypes: getSnapshot(filteredFeatureTypes),
|
|
234
|
+
onUpdate: (types: string[]) => {
|
|
235
|
+
self.updateFilteredFeatureTypes(types)
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
)
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
.actions((self) => ({
|
|
247
|
+
setSelectedFeature(feature?: AnnotationFeature) {
|
|
248
|
+
;(
|
|
249
|
+
self.session as unknown as ApolloSessionModel
|
|
250
|
+
).apolloSetSelectedFeature(feature)
|
|
251
|
+
},
|
|
252
|
+
showFeatureDetailsWidget(
|
|
253
|
+
feature: AnnotationFeature,
|
|
254
|
+
customWidgetNameAndId?: [string, string],
|
|
255
|
+
) {
|
|
256
|
+
const [region] = self.regions
|
|
257
|
+
const { assemblyName, refName } = region
|
|
258
|
+
const assembly = self.getAssemblyId(assemblyName)
|
|
259
|
+
if (!assembly) {
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
const { session } = self
|
|
263
|
+
const { changeManager } = session.apolloDataStore
|
|
264
|
+
const [widgetName, widgetId] = customWidgetNameAndId ?? [
|
|
265
|
+
'ApolloFeatureDetailsWidget',
|
|
266
|
+
'apolloFeatureDetailsWidget',
|
|
267
|
+
]
|
|
268
|
+
const apolloFeatureWidget = (
|
|
269
|
+
session as unknown as SessionWithWidgets
|
|
270
|
+
).addWidget(widgetName, widgetId, {
|
|
271
|
+
feature,
|
|
272
|
+
assembly,
|
|
273
|
+
refName,
|
|
274
|
+
changeManager,
|
|
275
|
+
})
|
|
276
|
+
;(session as unknown as SessionWithWidgets).showWidget(
|
|
277
|
+
apolloFeatureWidget,
|
|
278
|
+
)
|
|
279
|
+
},
|
|
280
|
+
afterAttach() {
|
|
281
|
+
addDisposer(
|
|
282
|
+
self,
|
|
283
|
+
autorun(
|
|
284
|
+
() => {
|
|
285
|
+
if (!self.lgv.initialized || self.regionCannotBeRendered()) {
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
void (
|
|
289
|
+
self.session as unknown as ApolloSessionModel
|
|
290
|
+
).apolloDataStore.loadFeatures(self.regions)
|
|
291
|
+
if (self.lgv.bpPerPx <= 3) {
|
|
292
|
+
void (
|
|
293
|
+
self.session as unknown as ApolloSessionModel
|
|
294
|
+
).apolloDataStore.loadRefSeq(self.regions)
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{ name: 'LinearApolloSixFrameDisplayLoadFeatures', delay: 1000 },
|
|
298
|
+
),
|
|
299
|
+
)
|
|
300
|
+
},
|
|
301
|
+
}))
|
|
302
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
+
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
3
|
+
import { type Instance, types } from 'mobx-state-tree'
|
|
4
|
+
|
|
5
|
+
import { TabularEditorStateModelType } from '../../TabularEditor'
|
|
6
|
+
|
|
7
|
+
import { mouseEventsModelFactory } from './mouseEvents'
|
|
8
|
+
|
|
9
|
+
export function stateModelFactory(
|
|
10
|
+
pluginManager: PluginManager,
|
|
11
|
+
configSchema: AnyConfigurationSchemaType,
|
|
12
|
+
) {
|
|
13
|
+
// TODO: this needs to be refactored so that the final composition of the
|
|
14
|
+
// state model mixins happens here in one central place
|
|
15
|
+
return mouseEventsModelFactory(pluginManager, configSchema)
|
|
16
|
+
.props({ tabularEditor: types.optional(TabularEditorStateModelType, {}) })
|
|
17
|
+
.named('LinearApolloSixFrameDisplay')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type LinearApolloSixFrameDisplayStateModel = ReturnType<
|
|
21
|
+
typeof stateModelFactory
|
|
22
|
+
>
|
|
23
|
+
// eslint disable because of
|
|
24
|
+
// https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
26
|
+
export interface LinearApolloSixFrameDisplay
|
|
27
|
+
extends Instance<LinearApolloSixFrameDisplayStateModel> {}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type AnnotationFeature,
|
|
5
|
+
type TranscriptPartCoding,
|
|
6
|
+
} from '@apollo-annotation/mst'
|
|
7
|
+
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
8
|
+
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
9
|
+
import {
|
|
10
|
+
type AbstractSessionModel,
|
|
11
|
+
doesIntersect2,
|
|
12
|
+
getFrame,
|
|
13
|
+
} from '@jbrowse/core/util'
|
|
14
|
+
import { autorun, observable } from 'mobx'
|
|
15
|
+
import { addDisposer, isAlive } from 'mobx-state-tree'
|
|
16
|
+
|
|
17
|
+
import { type ApolloSessionModel } from '../../session'
|
|
18
|
+
import { geneGlyph } from '../glyphs'
|
|
19
|
+
|
|
20
|
+
import { baseModelFactory } from './base'
|
|
21
|
+
|
|
22
|
+
export interface LayoutRow {
|
|
23
|
+
rowNum: number
|
|
24
|
+
feature: AnnotationFeature
|
|
25
|
+
cds: TranscriptPartCoding | null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function layoutsModelFactory(
|
|
29
|
+
pluginManager: PluginManager,
|
|
30
|
+
configSchema: AnyConfigurationSchemaType,
|
|
31
|
+
) {
|
|
32
|
+
const BaseLinearApolloSixFrameDisplay = baseModelFactory(
|
|
33
|
+
pluginManager,
|
|
34
|
+
configSchema,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return BaseLinearApolloSixFrameDisplay.named(
|
|
38
|
+
'LinearApolloSixFrameDisplayLayouts',
|
|
39
|
+
)
|
|
40
|
+
.props({
|
|
41
|
+
featuresMinMaxLimit: 500_000,
|
|
42
|
+
})
|
|
43
|
+
.volatile(() => ({
|
|
44
|
+
seenFeatures: observable.map<string, AnnotationFeature>(),
|
|
45
|
+
}))
|
|
46
|
+
.views((self) => ({
|
|
47
|
+
get featuresMinMax() {
|
|
48
|
+
const { assemblyManager } =
|
|
49
|
+
self.session as unknown as AbstractSessionModel
|
|
50
|
+
return self.lgv.displayedRegions.map((region) => {
|
|
51
|
+
const assembly = assemblyManager.get(region.assemblyName)
|
|
52
|
+
let min: number | undefined
|
|
53
|
+
let max: number | undefined
|
|
54
|
+
const { end, refName, start } = region
|
|
55
|
+
for (const [, feature] of self.seenFeatures) {
|
|
56
|
+
if (
|
|
57
|
+
refName !== assembly?.getCanonicalRefName(feature.refSeq) ||
|
|
58
|
+
!doesIntersect2(start, end, feature.min, feature.max) ||
|
|
59
|
+
feature.length > self.featuresMinMaxLimit
|
|
60
|
+
) {
|
|
61
|
+
continue
|
|
62
|
+
}
|
|
63
|
+
if (min === undefined) {
|
|
64
|
+
;({ min } = feature)
|
|
65
|
+
}
|
|
66
|
+
if (max === undefined) {
|
|
67
|
+
;({ max } = feature)
|
|
68
|
+
}
|
|
69
|
+
if (feature.minWithChildren < min) {
|
|
70
|
+
;({ min } = feature)
|
|
71
|
+
}
|
|
72
|
+
if (feature.maxWithChildren > max) {
|
|
73
|
+
;({ max } = feature)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (min !== undefined && max !== undefined) {
|
|
77
|
+
return [min, max]
|
|
78
|
+
}
|
|
79
|
+
return
|
|
80
|
+
})
|
|
81
|
+
},
|
|
82
|
+
getGlyph(_feature: AnnotationFeature) {
|
|
83
|
+
return geneGlyph
|
|
84
|
+
},
|
|
85
|
+
featureLabelSpacer(elem: number): number {
|
|
86
|
+
return self.showFeatureLabels ? elem * 2 - 1 : elem
|
|
87
|
+
},
|
|
88
|
+
}))
|
|
89
|
+
.actions((self) => ({
|
|
90
|
+
addSeenFeature(feature: AnnotationFeature) {
|
|
91
|
+
self.seenFeatures.set(feature._id, feature)
|
|
92
|
+
},
|
|
93
|
+
deleteSeenFeature(featureId: string) {
|
|
94
|
+
self.seenFeatures.delete(featureId)
|
|
95
|
+
},
|
|
96
|
+
}))
|
|
97
|
+
.views((self) => ({
|
|
98
|
+
get geneTrackRowNums() {
|
|
99
|
+
return [4, 5].map((elem) => self.featureLabelSpacer(elem))
|
|
100
|
+
},
|
|
101
|
+
}))
|
|
102
|
+
.views((self) => ({
|
|
103
|
+
get featureLayouts() {
|
|
104
|
+
const { assemblyManager } =
|
|
105
|
+
self.session as unknown as AbstractSessionModel
|
|
106
|
+
return self.lgv.displayedRegions.map((region, idx) => {
|
|
107
|
+
const assembly = assemblyManager.get(region.assemblyName)
|
|
108
|
+
const featureLayout = new Map<number, LayoutRow[]>()
|
|
109
|
+
const minMax = self.featuresMinMax[idx]
|
|
110
|
+
if (!minMax) {
|
|
111
|
+
return featureLayout
|
|
112
|
+
}
|
|
113
|
+
const { end, refName, start } = region
|
|
114
|
+
for (const [id, feature] of self.seenFeatures.entries()) {
|
|
115
|
+
if (!isAlive(feature)) {
|
|
116
|
+
self.deleteSeenFeature(id)
|
|
117
|
+
continue
|
|
118
|
+
}
|
|
119
|
+
if (
|
|
120
|
+
refName !== assembly?.getCanonicalRefName(feature.refSeq) ||
|
|
121
|
+
!doesIntersect2(start, end, feature.min, feature.max)
|
|
122
|
+
) {
|
|
123
|
+
continue
|
|
124
|
+
}
|
|
125
|
+
const { featureTypeOntology } =
|
|
126
|
+
self.session.apolloDataStore.ontologyManager
|
|
127
|
+
if (!featureTypeOntology) {
|
|
128
|
+
throw new Error('featureTypeOntology is undefined')
|
|
129
|
+
}
|
|
130
|
+
if (feature.looksLikeGene) {
|
|
131
|
+
const rowNum =
|
|
132
|
+
feature.strand == 1
|
|
133
|
+
? self.geneTrackRowNums[0]
|
|
134
|
+
: self.geneTrackRowNums[1]
|
|
135
|
+
if (!featureLayout.get(rowNum)) {
|
|
136
|
+
featureLayout.set(rowNum, [])
|
|
137
|
+
}
|
|
138
|
+
const layoutRow = featureLayout.get(rowNum)
|
|
139
|
+
layoutRow?.push({ rowNum, feature, cds: null })
|
|
140
|
+
const { children } = feature
|
|
141
|
+
if (!children) {
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
for (const [, child] of children) {
|
|
145
|
+
if (featureTypeOntology.isTypeOf(child.type, 'transcript')) {
|
|
146
|
+
const {
|
|
147
|
+
cdsLocations,
|
|
148
|
+
strand,
|
|
149
|
+
children: childrenOfmRNA,
|
|
150
|
+
} = child
|
|
151
|
+
if (childrenOfmRNA) {
|
|
152
|
+
for (const [, exon] of childrenOfmRNA) {
|
|
153
|
+
if (!featureTypeOntology.isTypeOf(exon.type, 'exon')) {
|
|
154
|
+
continue
|
|
155
|
+
}
|
|
156
|
+
const rowNum =
|
|
157
|
+
exon.strand == 1
|
|
158
|
+
? self.geneTrackRowNums[0]
|
|
159
|
+
: self.geneTrackRowNums[1]
|
|
160
|
+
const layoutRow = featureLayout.get(rowNum)
|
|
161
|
+
layoutRow?.push({ rowNum, feature: exon, cds: null })
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const cdsRow of cdsLocations) {
|
|
165
|
+
for (const cds of cdsRow) {
|
|
166
|
+
let rowNum: number = getFrame(
|
|
167
|
+
cds.min,
|
|
168
|
+
cds.max,
|
|
169
|
+
strand ?? 1,
|
|
170
|
+
cds.phase,
|
|
171
|
+
)
|
|
172
|
+
rowNum = self.featureLabelSpacer(
|
|
173
|
+
rowNum < 0 ? -1 * rowNum + 5 : rowNum,
|
|
174
|
+
)
|
|
175
|
+
if (!featureLayout.get(rowNum)) {
|
|
176
|
+
featureLayout.set(rowNum, [])
|
|
177
|
+
}
|
|
178
|
+
const layoutRow = featureLayout.get(rowNum)
|
|
179
|
+
layoutRow?.push({ rowNum, feature: child, cds })
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
continue
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return featureLayout
|
|
189
|
+
})
|
|
190
|
+
},
|
|
191
|
+
getFeatureLayoutPosition(feature: AnnotationFeature) {
|
|
192
|
+
const { featureLayouts } = this
|
|
193
|
+
for (const [idx, layout] of featureLayouts.entries()) {
|
|
194
|
+
for (const [, layoutRow] of layout) {
|
|
195
|
+
for (const { feature: layoutFeature } of layoutRow) {
|
|
196
|
+
if (feature._id === layoutFeature._id) {
|
|
197
|
+
return {
|
|
198
|
+
layoutIndex: idx,
|
|
199
|
+
layoutRow: 0,
|
|
200
|
+
featureRow: 0,
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return
|
|
207
|
+
},
|
|
208
|
+
}))
|
|
209
|
+
.views((_self) => ({
|
|
210
|
+
get highestRow() {
|
|
211
|
+
return 5
|
|
212
|
+
},
|
|
213
|
+
}))
|
|
214
|
+
.actions((self) => ({
|
|
215
|
+
afterAttach() {
|
|
216
|
+
addDisposer(
|
|
217
|
+
self,
|
|
218
|
+
autorun(
|
|
219
|
+
() => {
|
|
220
|
+
if (!self.lgv.initialized || self.regionCannotBeRendered()) {
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
for (const region of self.regions) {
|
|
224
|
+
const assembly = (
|
|
225
|
+
self.session as unknown as ApolloSessionModel
|
|
226
|
+
).apolloDataStore.assemblies.get(region.assemblyName)
|
|
227
|
+
const ref = assembly?.getByRefName(region.refName)
|
|
228
|
+
const features = ref?.features
|
|
229
|
+
if (!features) {
|
|
230
|
+
continue
|
|
231
|
+
}
|
|
232
|
+
for (const [, feature] of features) {
|
|
233
|
+
if (
|
|
234
|
+
doesIntersect2(
|
|
235
|
+
region.start,
|
|
236
|
+
region.end,
|
|
237
|
+
feature.min,
|
|
238
|
+
feature.max,
|
|
239
|
+
) &&
|
|
240
|
+
!self.seenFeatures.has(feature._id)
|
|
241
|
+
) {
|
|
242
|
+
self.addSeenFeature(feature)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
{ name: 'LinearApolloSixFrameDisplaySetSeenFeatures', delay: 1000 },
|
|
248
|
+
),
|
|
249
|
+
)
|
|
250
|
+
},
|
|
251
|
+
}))
|
|
252
|
+
}
|