@apollo-annotation/jbrowse-plugin-apollo 0.1.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.
- package/README.md +76 -0
- package/dist/index.esm.js +10248 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +7 -0
- package/dist/jbrowse-plugin-apollo.cjs.development.js +10298 -0
- package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -0
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js +2 -0
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -0
- package/dist/jbrowse-plugin-apollo.umd.development.js +46957 -0
- package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -0
- package/dist/jbrowse-plugin-apollo.umd.production.min.js +2 -0
- package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -0
- package/package.json +130 -0
- package/src/ApolloInternetAccount/addMenuItems.ts +94 -0
- package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +121 -0
- package/src/ApolloInternetAccount/components/LoginButtons.tsx +62 -0
- package/src/ApolloInternetAccount/components/LoginIcons.tsx +74 -0
- package/src/ApolloInternetAccount/configSchema.ts +26 -0
- package/src/ApolloInternetAccount/index.ts +2 -0
- package/src/ApolloInternetAccount/model.ts +448 -0
- package/src/ApolloJobModel.ts +117 -0
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +186 -0
- package/src/ApolloSequenceAdapter/configSchema.ts +12 -0
- package/src/ApolloSequenceAdapter/index.ts +21 -0
- package/src/ApolloSixFrameRenderer/ApolloSixFrameRenderer.tsx +12 -0
- package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +692 -0
- package/src/ApolloSixFrameRenderer/configSchema.ts +7 -0
- package/src/ApolloSixFrameRenderer/index.ts +3 -0
- package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +64 -0
- package/src/ApolloTextSearchAdapter/configSchema.ts +24 -0
- package/src/ApolloTextSearchAdapter/index.ts +18 -0
- package/src/BackendDrivers/BackendDriver.ts +31 -0
- package/src/BackendDrivers/CollaborationServerDriver.ts +318 -0
- package/src/BackendDrivers/DesktopFileDriver.ts +170 -0
- package/src/BackendDrivers/InMemoryFileDriver.ts +76 -0
- package/src/BackendDrivers/index.ts +4 -0
- package/src/ChangeManager.ts +148 -0
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +248 -0
- package/src/LinearApolloDisplay/components/index.ts +1 -0
- package/src/LinearApolloDisplay/configSchema.ts +16 -0
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +422 -0
- package/src/LinearApolloDisplay/glyphs/CanonicalGeneGlyph.ts +1191 -0
- package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +151 -0
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +382 -0
- package/src/LinearApolloDisplay/glyphs/ImplicitExonGeneGlyph.ts +697 -0
- package/src/LinearApolloDisplay/glyphs/index.ts +4 -0
- package/src/LinearApolloDisplay/index.ts +2 -0
- package/src/LinearApolloDisplay/stateModel/base.ts +146 -0
- package/src/LinearApolloDisplay/stateModel/getGlyph.ts +39 -0
- package/src/LinearApolloDisplay/stateModel/glyphs.ts +45 -0
- package/src/LinearApolloDisplay/stateModel/index.ts +20 -0
- package/src/LinearApolloDisplay/stateModel/layouts.ts +230 -0
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +513 -0
- package/src/LinearApolloDisplay/stateModel/rendering.ts +441 -0
- package/src/LinearApolloDisplay/stateModel/trackHeightMixin.ts +43 -0
- package/src/LinearApolloDisplay/types.ts +1 -0
- package/src/OntologyManager/OntologyStore/__snapshots__/fulltext.test.ts.snap +208 -0
- package/src/OntologyManager/OntologyStore/__snapshots__/index.test.ts.snap +18846 -0
- package/src/OntologyManager/OntologyStore/fulltext-stopwords.ts +137 -0
- package/src/OntologyManager/OntologyStore/fulltext.test.ts +94 -0
- package/src/OntologyManager/OntologyStore/fulltext.ts +264 -0
- package/src/OntologyManager/OntologyStore/index.test.ts +130 -0
- package/src/OntologyManager/OntologyStore/index.ts +526 -0
- package/src/OntologyManager/OntologyStore/indexeddb-schema.ts +89 -0
- package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +180 -0
- package/src/OntologyManager/OntologyStore/obo-graph-json-schema.ts +110 -0
- package/src/OntologyManager/OntologyStore/prefixes.ts +35 -0
- package/src/OntologyManager/index.ts +173 -0
- package/src/SixFrameFeatureDisplay/components/TrackLines.tsx +19 -0
- package/src/SixFrameFeatureDisplay/components/index.ts +1 -0
- package/src/SixFrameFeatureDisplay/configSchema.ts +21 -0
- package/src/SixFrameFeatureDisplay/index.ts +2 -0
- package/src/SixFrameFeatureDisplay/stateModel.ts +413 -0
- package/src/TabularEditor/HybridGrid/ChangeHandling.ts +88 -0
- package/src/TabularEditor/HybridGrid/Feature.tsx +346 -0
- package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +34 -0
- package/src/TabularEditor/HybridGrid/Highlight.tsx +40 -0
- package/src/TabularEditor/HybridGrid/HybridGrid.tsx +138 -0
- package/src/TabularEditor/HybridGrid/NumberCell.tsx +77 -0
- package/src/TabularEditor/HybridGrid/ToolBar.tsx +59 -0
- package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +119 -0
- package/src/TabularEditor/HybridGrid/index.ts +1 -0
- package/src/TabularEditor/TabularEditorPane.tsx +34 -0
- package/src/TabularEditor/index.ts +3 -0
- package/src/TabularEditor/model.ts +44 -0
- package/src/TabularEditor/types.ts +3 -0
- package/src/components/AddAssembly.tsx +464 -0
- package/src/components/AddChildFeature.tsx +247 -0
- package/src/components/AddFeature.tsx +252 -0
- package/src/components/CopyFeature.tsx +328 -0
- package/src/components/DeleteAssembly.tsx +185 -0
- package/src/components/DeleteFeature.tsx +90 -0
- package/src/components/Dialog.tsx +47 -0
- package/src/components/DownloadGFF3.tsx +213 -0
- package/src/components/ImportFeatures.tsx +295 -0
- package/src/components/ManageChecks.tsx +280 -0
- package/src/components/ManageUsers.tsx +218 -0
- package/src/components/ModifyFeatureAttribute.tsx +457 -0
- package/src/components/OntologyTermAutocomplete.tsx +240 -0
- package/src/components/OntologyTermMultiSelect.tsx +349 -0
- package/src/components/OpenLocalFile.tsx +178 -0
- package/src/components/ViewChangeLog.tsx +208 -0
- package/src/components/ViewCheckResults.tsx +151 -0
- package/src/components/index.ts +12 -0
- package/src/config.ts +10 -0
- package/src/declare.d.ts +3 -0
- package/src/extensions/annotationFromPileup.ts +208 -0
- package/src/extensions/index.ts +1 -0
- package/src/index.ts +394 -0
- package/src/makeDisplayComponent.tsx +244 -0
- package/src/session/ClientDataStore.ts +282 -0
- package/src/session/index.ts +1 -0
- package/src/session/session.ts +373 -0
- package/src/types.ts +10 -0
- package/src/util/index.ts +31 -0
- package/src/util/loadAssemblyIntoClient.ts +291 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { ConfigurationReference } from '@jbrowse/core/configuration'
|
|
2
|
+
import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
3
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
4
|
+
import {
|
|
5
|
+
defaultStarts,
|
|
6
|
+
defaultStops,
|
|
7
|
+
getContainingView,
|
|
8
|
+
getSession,
|
|
9
|
+
revcom,
|
|
10
|
+
reverse,
|
|
11
|
+
} from '@jbrowse/core/util'
|
|
12
|
+
import { BaseBlock } from '@jbrowse/core/util/blockTypes'
|
|
13
|
+
import { getParentRenderProps } from '@jbrowse/core/util/tracks'
|
|
14
|
+
import type LinearGenomeViewPlugin from '@jbrowse/plugin-linear-genome-view'
|
|
15
|
+
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
16
|
+
import { AnnotationFeatureI } from 'apollo-mst'
|
|
17
|
+
import { autorun } from 'mobx'
|
|
18
|
+
import { Instance, addDisposer, types } from 'mobx-state-tree'
|
|
19
|
+
|
|
20
|
+
import { ApolloSession, ApolloSessionModel } from '../session'
|
|
21
|
+
|
|
22
|
+
const forwardPhaseMap: Record<number, number> = { 0: 2, 1: 1, 2: 0 }
|
|
23
|
+
const reversePhaseMap: Record<number, number> = { 3: 0, 4: 1, 5: 2 }
|
|
24
|
+
|
|
25
|
+
export function stateModelFactory(
|
|
26
|
+
pluginManager: PluginManager,
|
|
27
|
+
configSchema: AnyConfigurationSchemaType,
|
|
28
|
+
) {
|
|
29
|
+
const LGVPlugin = pluginManager.getPlugin(
|
|
30
|
+
'LinearGenomeViewPlugin',
|
|
31
|
+
) as LinearGenomeViewPlugin
|
|
32
|
+
const { BaseLinearDisplay } = LGVPlugin.exports
|
|
33
|
+
|
|
34
|
+
return BaseLinearDisplay.named('SixFrameFeatureDisplay')
|
|
35
|
+
.props({
|
|
36
|
+
type: types.literal('SixFrameFeatureDisplay'),
|
|
37
|
+
configuration: ConfigurationReference(configSchema),
|
|
38
|
+
apolloRowHeight: 20,
|
|
39
|
+
detailsMinHeight: 200,
|
|
40
|
+
showStartCodons: false,
|
|
41
|
+
showStopCodons: true,
|
|
42
|
+
showIntronLines: true,
|
|
43
|
+
})
|
|
44
|
+
.volatile(() => ({
|
|
45
|
+
apolloFeatureUnderMouse: undefined as AnnotationFeatureI | undefined,
|
|
46
|
+
apolloRowUnderMouse: undefined as number | undefined,
|
|
47
|
+
}))
|
|
48
|
+
.views((self) => {
|
|
49
|
+
const { configuration, renderProps: superRenderProps } = self
|
|
50
|
+
return {
|
|
51
|
+
renderProps() {
|
|
52
|
+
return {
|
|
53
|
+
...superRenderProps(),
|
|
54
|
+
...getParentRenderProps(self),
|
|
55
|
+
config: configuration.renderer,
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
.views((self) => ({
|
|
61
|
+
get regions() {
|
|
62
|
+
let blockDefinitions
|
|
63
|
+
try {
|
|
64
|
+
;({ blockDefinitions } = self)
|
|
65
|
+
} catch {
|
|
66
|
+
return []
|
|
67
|
+
}
|
|
68
|
+
const regions = blockDefinitions.contentBlocks.map(
|
|
69
|
+
({ assemblyName, end, refName, start }) => ({
|
|
70
|
+
assemblyName,
|
|
71
|
+
refName,
|
|
72
|
+
start,
|
|
73
|
+
end,
|
|
74
|
+
}),
|
|
75
|
+
)
|
|
76
|
+
return regions
|
|
77
|
+
},
|
|
78
|
+
regionCannotBeRendered(/* region */) {
|
|
79
|
+
const view = getContainingView(self) as unknown as LinearGenomeViewModel
|
|
80
|
+
if (view && view.bpPerPx >= 200) {
|
|
81
|
+
return 'Zoom in to see annotations'
|
|
82
|
+
}
|
|
83
|
+
return
|
|
84
|
+
},
|
|
85
|
+
get session() {
|
|
86
|
+
return getSession(self) as unknown as ApolloSessionModel
|
|
87
|
+
},
|
|
88
|
+
}))
|
|
89
|
+
.actions((self) => {
|
|
90
|
+
let previousBlockKeys: string[] = []
|
|
91
|
+
return {
|
|
92
|
+
afterAttach() {
|
|
93
|
+
addDisposer(
|
|
94
|
+
self,
|
|
95
|
+
autorun(
|
|
96
|
+
() => {
|
|
97
|
+
const session = getSession(self) as ApolloSession
|
|
98
|
+
const view = getContainingView(
|
|
99
|
+
self,
|
|
100
|
+
) as unknown as LinearGenomeViewModel
|
|
101
|
+
if (view.initialized) {
|
|
102
|
+
if (self.regionCannotBeRendered()) {
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
const blockKeys: string[] = []
|
|
106
|
+
const newBlocks: BaseBlock[] = []
|
|
107
|
+
for (const block of self.blockDefinitions.contentBlocks) {
|
|
108
|
+
blockKeys.push(block.key)
|
|
109
|
+
if (!previousBlockKeys.includes(block.key)) {
|
|
110
|
+
newBlocks.push(block)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
session.apolloDataStore.loadFeatures(
|
|
114
|
+
newBlocks.map(({ assemblyName, end, refName, start }) => ({
|
|
115
|
+
assemblyName,
|
|
116
|
+
refName,
|
|
117
|
+
start,
|
|
118
|
+
end,
|
|
119
|
+
})),
|
|
120
|
+
)
|
|
121
|
+
session.apolloDataStore.loadRefSeq(
|
|
122
|
+
newBlocks.map(({ assemblyName, end, refName, start }) => ({
|
|
123
|
+
assemblyName,
|
|
124
|
+
refName,
|
|
125
|
+
start,
|
|
126
|
+
end,
|
|
127
|
+
})),
|
|
128
|
+
)
|
|
129
|
+
previousBlockKeys = blockKeys
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{ name: 'SixFrameFeatureDisplay' },
|
|
133
|
+
),
|
|
134
|
+
)
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
.views((self) => ({
|
|
139
|
+
get rendererTypeName() {
|
|
140
|
+
return self.configuration.renderer.type
|
|
141
|
+
},
|
|
142
|
+
get changeManager() {
|
|
143
|
+
const session = getSession(self) as ApolloSession
|
|
144
|
+
return session.apolloDataStore?.changeManager
|
|
145
|
+
},
|
|
146
|
+
get sequence() {
|
|
147
|
+
const { regions } = self
|
|
148
|
+
const session = getSession(self) as ApolloSession
|
|
149
|
+
const seq = new Map<number, string>()
|
|
150
|
+
for (const region of regions) {
|
|
151
|
+
const assembly = session.apolloDataStore.assemblies.get(
|
|
152
|
+
region.assemblyName,
|
|
153
|
+
)
|
|
154
|
+
const ref = assembly?.getByRefName(region.refName)
|
|
155
|
+
const refSeq: string | undefined = ref?.getSequence(
|
|
156
|
+
region.start,
|
|
157
|
+
region.end,
|
|
158
|
+
)
|
|
159
|
+
seq.set(region.start, refSeq ?? '')
|
|
160
|
+
}
|
|
161
|
+
return seq
|
|
162
|
+
},
|
|
163
|
+
get features() {
|
|
164
|
+
const { regions } = self
|
|
165
|
+
const session = getSession(self) as ApolloSession
|
|
166
|
+
const features = new Map<string, Map<string, AnnotationFeatureI>>()
|
|
167
|
+
for (const region of regions) {
|
|
168
|
+
const assembly = session.apolloDataStore.assemblies.get(
|
|
169
|
+
region.assemblyName,
|
|
170
|
+
)
|
|
171
|
+
const ref = assembly?.getByRefName(region.refName)
|
|
172
|
+
let filteredRef = features.get(region.refName)
|
|
173
|
+
if (!filteredRef) {
|
|
174
|
+
filteredRef = new Map<string, AnnotationFeatureI>()
|
|
175
|
+
features.set(region.refName, filteredRef)
|
|
176
|
+
}
|
|
177
|
+
for (const [featureId, feature] of ref?.features.entries() ??
|
|
178
|
+
new Map()) {
|
|
179
|
+
if (region.start < feature.end && region.end > feature.start) {
|
|
180
|
+
filteredRef.set(featureId, feature)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return features
|
|
185
|
+
},
|
|
186
|
+
get featuresMinMax() {
|
|
187
|
+
const minMax: Record<string, [number, number]> = {}
|
|
188
|
+
for (const [refSeq, featuresForRefSeq] of this.features || []) {
|
|
189
|
+
let min: number | undefined
|
|
190
|
+
let max: number | undefined
|
|
191
|
+
for (const [, featureLocation] of featuresForRefSeq) {
|
|
192
|
+
if (min === undefined) {
|
|
193
|
+
;({ min } = featureLocation)
|
|
194
|
+
}
|
|
195
|
+
if (max === undefined) {
|
|
196
|
+
;({ max } = featureLocation)
|
|
197
|
+
}
|
|
198
|
+
if (featureLocation.min < min) {
|
|
199
|
+
;({ min } = featureLocation)
|
|
200
|
+
}
|
|
201
|
+
if (featureLocation.end > max) {
|
|
202
|
+
;({ max } = featureLocation)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (min !== undefined && max !== undefined) {
|
|
206
|
+
minMax[refSeq] = [min, max]
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return minMax
|
|
210
|
+
},
|
|
211
|
+
get codonLayout() {
|
|
212
|
+
const codonLayout = new Map<
|
|
213
|
+
number,
|
|
214
|
+
{ starts: number[]; stops: number[] }
|
|
215
|
+
>()
|
|
216
|
+
let fullSeq = ''
|
|
217
|
+
let fullStart = 0
|
|
218
|
+
for (const [regionStart, seq] of this.sequence || []) {
|
|
219
|
+
if (!seq) {
|
|
220
|
+
continue
|
|
221
|
+
}
|
|
222
|
+
if (!fullSeq) {
|
|
223
|
+
fullStart = regionStart
|
|
224
|
+
}
|
|
225
|
+
fullSeq += seq
|
|
226
|
+
}
|
|
227
|
+
const rowCount = 6
|
|
228
|
+
for (let i = 0; i < rowCount; i++) {
|
|
229
|
+
const starts: number[] = []
|
|
230
|
+
const stops: number[] = []
|
|
231
|
+
const reversed = i in reversePhaseMap
|
|
232
|
+
// the tilt variable normalizes the frame to where we are starting from,
|
|
233
|
+
// which increases consistency across blocks
|
|
234
|
+
let tilt
|
|
235
|
+
// the effectiveFrame incorporates tilt and the frame to say what the
|
|
236
|
+
// effective frame that is plotted. The +3 is for when frame is -2 and this
|
|
237
|
+
// can otherwise result in effectiveFrame -1
|
|
238
|
+
let effectiveFrame
|
|
239
|
+
let seqSliced
|
|
240
|
+
if (reversed) {
|
|
241
|
+
tilt = (fullSeq.length + fullStart) % 3
|
|
242
|
+
effectiveFrame = (reversePhaseMap[i] + tilt + 3) % 3
|
|
243
|
+
seqSliced = reverse(fullSeq).slice(effectiveFrame)
|
|
244
|
+
} else {
|
|
245
|
+
tilt = 3 - (fullStart % 3)
|
|
246
|
+
effectiveFrame = (forwardPhaseMap[i] + tilt + 3) % 3
|
|
247
|
+
seqSliced = fullSeq.slice(effectiveFrame)
|
|
248
|
+
}
|
|
249
|
+
for (let j = 0; j < seqSliced.length; j += 3) {
|
|
250
|
+
const codon = seqSliced.slice(j, j + 3)
|
|
251
|
+
const normalizedCodon = reversed ? reverse(revcom(codon)) : codon
|
|
252
|
+
const start = reversed
|
|
253
|
+
? fullStart + seqSliced.length - (3 + j)
|
|
254
|
+
: fullStart + j + effectiveFrame
|
|
255
|
+
if (defaultStarts.includes(normalizedCodon.toUpperCase())) {
|
|
256
|
+
starts.push(start)
|
|
257
|
+
} else if (defaultStops.includes(normalizedCodon.toUpperCase())) {
|
|
258
|
+
stops.push(start)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
codonLayout.set(i, { starts, stops })
|
|
262
|
+
}
|
|
263
|
+
return codonLayout
|
|
264
|
+
},
|
|
265
|
+
get featureLayout() {
|
|
266
|
+
const featureLayout = new Map<number, [string, AnnotationFeatureI][]>()
|
|
267
|
+
for (const [refSeq, featuresForRefSeq] of this.features || []) {
|
|
268
|
+
if (!featuresForRefSeq) {
|
|
269
|
+
continue
|
|
270
|
+
}
|
|
271
|
+
const minMaxfeatures = this.featuresMinMax[refSeq]
|
|
272
|
+
if (!minMaxfeatures) {
|
|
273
|
+
continue
|
|
274
|
+
}
|
|
275
|
+
const [min, max] = minMaxfeatures
|
|
276
|
+
const rows: boolean[][] = []
|
|
277
|
+
const rowCount = 6
|
|
278
|
+
for (let i = 0; i < rowCount; i++) {
|
|
279
|
+
const newRowNumber = rows.length
|
|
280
|
+
rows[newRowNumber] = Array.from({ length: max - min })
|
|
281
|
+
featureLayout.set(newRowNumber, [])
|
|
282
|
+
}
|
|
283
|
+
for (const feature of [...featuresForRefSeq.values()].sort(
|
|
284
|
+
(f1, f2) => {
|
|
285
|
+
const { max: end1, min: start1 } = f1
|
|
286
|
+
const { max: end2, min: start2 } = f2
|
|
287
|
+
return start1 - start2 || end1 - end2
|
|
288
|
+
},
|
|
289
|
+
)) {
|
|
290
|
+
for (const [, childFeature] of feature.children ?? new Map()) {
|
|
291
|
+
if (childFeature.type === 'mRNA') {
|
|
292
|
+
for (const [, grandChildFeature] of childFeature.children ||
|
|
293
|
+
new Map()) {
|
|
294
|
+
let startingRow
|
|
295
|
+
if (grandChildFeature.type === 'CDS') {
|
|
296
|
+
let discontinuousLocations
|
|
297
|
+
if (grandChildFeature.discontinuousLocations.length > 0) {
|
|
298
|
+
;({ discontinuousLocations } = grandChildFeature)
|
|
299
|
+
} else {
|
|
300
|
+
discontinuousLocations = [grandChildFeature]
|
|
301
|
+
}
|
|
302
|
+
for (const cds of discontinuousLocations) {
|
|
303
|
+
const min = cds.start + 3
|
|
304
|
+
const max = cds.end - 3
|
|
305
|
+
// Remove codons either end of feature when considering intersect.
|
|
306
|
+
for (const [row, { stops }] of this.codonLayout) {
|
|
307
|
+
if (
|
|
308
|
+
(row < 3 && feature.strand === 1) ||
|
|
309
|
+
(row >= 3 && feature.strand === -1)
|
|
310
|
+
) {
|
|
311
|
+
const filteredArray = stops.filter(
|
|
312
|
+
(value) => value >= min && value <= max,
|
|
313
|
+
)
|
|
314
|
+
if (filteredArray.length === 0) {
|
|
315
|
+
startingRow = row
|
|
316
|
+
const layoutRow = featureLayout.get(startingRow)
|
|
317
|
+
layoutRow?.push([childFeature.featureId, cds])
|
|
318
|
+
break
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return featureLayout
|
|
330
|
+
},
|
|
331
|
+
getAssemblyId(assemblyName: string) {
|
|
332
|
+
const { assemblyManager } = getSession(self)
|
|
333
|
+
const assembly = assemblyManager.get(assemblyName)
|
|
334
|
+
if (!assembly) {
|
|
335
|
+
throw new Error(`Could not find assembly named ${assemblyName}`)
|
|
336
|
+
}
|
|
337
|
+
return assembly.name
|
|
338
|
+
},
|
|
339
|
+
get selectedFeature(): AnnotationFeatureI | undefined {
|
|
340
|
+
const session = getSession(self) as ApolloSession
|
|
341
|
+
return session.apolloSelectedFeature
|
|
342
|
+
},
|
|
343
|
+
get setSelectedFeature() {
|
|
344
|
+
const session = getSession(self) as ApolloSession
|
|
345
|
+
return session.apolloSetSelectedFeature
|
|
346
|
+
},
|
|
347
|
+
}))
|
|
348
|
+
.actions((self) => ({
|
|
349
|
+
setSelectedFeature(feature?: AnnotationFeatureI) {
|
|
350
|
+
const session = getSession(self) as ApolloSession
|
|
351
|
+
return session.apolloSetSelectedFeature(feature)
|
|
352
|
+
},
|
|
353
|
+
setApolloFeatureUnderMouse(feature?: AnnotationFeatureI) {
|
|
354
|
+
self.apolloFeatureUnderMouse = feature
|
|
355
|
+
},
|
|
356
|
+
setApolloRowUnderMouse(row?: number) {
|
|
357
|
+
self.apolloRowUnderMouse = row
|
|
358
|
+
},
|
|
359
|
+
toggleShowStartCodons() {
|
|
360
|
+
self.showStartCodons = !self.showStartCodons
|
|
361
|
+
},
|
|
362
|
+
toggleShowStopCodons() {
|
|
363
|
+
self.showStopCodons = !self.showStopCodons
|
|
364
|
+
},
|
|
365
|
+
toggleShowIntronLines() {
|
|
366
|
+
self.showIntronLines = !self.showIntronLines
|
|
367
|
+
},
|
|
368
|
+
}))
|
|
369
|
+
.views((self) => ({
|
|
370
|
+
get highestRow() {
|
|
371
|
+
if (self.featureLayout.size === 0) {
|
|
372
|
+
return 0
|
|
373
|
+
}
|
|
374
|
+
return Math.max(...self.featureLayout.keys())
|
|
375
|
+
},
|
|
376
|
+
get featuresHeight() {
|
|
377
|
+
return (this.highestRow + 1) * self.apolloRowHeight
|
|
378
|
+
},
|
|
379
|
+
get detailsHeight() {
|
|
380
|
+
return Math.max(
|
|
381
|
+
self.detailsMinHeight,
|
|
382
|
+
self.height - this.featuresHeight,
|
|
383
|
+
)
|
|
384
|
+
},
|
|
385
|
+
trackMenuItems() {
|
|
386
|
+
return [
|
|
387
|
+
{
|
|
388
|
+
label: 'Show start codons',
|
|
389
|
+
type: 'checkbox',
|
|
390
|
+
checked: self.showStartCodons,
|
|
391
|
+
onClick: () => self.toggleShowStartCodons(),
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
label: 'Show stop codons',
|
|
395
|
+
type: 'checkbox',
|
|
396
|
+
checked: self.showStopCodons,
|
|
397
|
+
onClick: () => self.toggleShowStopCodons(),
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
label: 'Show intron lines',
|
|
401
|
+
type: 'checkbox',
|
|
402
|
+
checked: self.showIntronLines,
|
|
403
|
+
onClick: () => self.toggleShowIntronLines(),
|
|
404
|
+
},
|
|
405
|
+
]
|
|
406
|
+
},
|
|
407
|
+
}))
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export type SixFrameFeatureDisplayStateModel = ReturnType<
|
|
411
|
+
typeof stateModelFactory
|
|
412
|
+
>
|
|
413
|
+
export type SixFrameFeatureDisplay = Instance<SixFrameFeatureDisplayStateModel>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { AnnotationFeatureI } from 'apollo-mst'
|
|
2
|
+
import {
|
|
3
|
+
DiscontinuousLocationEndChange,
|
|
4
|
+
DiscontinuousLocationStartChange,
|
|
5
|
+
LocationEndChange,
|
|
6
|
+
LocationStartChange,
|
|
7
|
+
TypeChange,
|
|
8
|
+
} from 'apollo-shared'
|
|
9
|
+
|
|
10
|
+
import type { ChangeManager } from '../../ChangeManager'
|
|
11
|
+
|
|
12
|
+
export function handleFeatureTypeChange(
|
|
13
|
+
changeManager: ChangeManager,
|
|
14
|
+
feature: AnnotationFeatureI,
|
|
15
|
+
oldType: string,
|
|
16
|
+
newType: string,
|
|
17
|
+
) {
|
|
18
|
+
const featureId = feature._id
|
|
19
|
+
const change = new TypeChange({
|
|
20
|
+
typeName: 'TypeChange',
|
|
21
|
+
changedIds: [featureId],
|
|
22
|
+
featureId,
|
|
23
|
+
oldType: String(oldType),
|
|
24
|
+
newType: String(newType),
|
|
25
|
+
assembly: feature.assemblyId,
|
|
26
|
+
})
|
|
27
|
+
return changeManager.submit(change)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function handleFeatureStartChange(
|
|
31
|
+
changeManager: ChangeManager,
|
|
32
|
+
feature: AnnotationFeatureI,
|
|
33
|
+
oldStart: number,
|
|
34
|
+
newStart: number,
|
|
35
|
+
index?: number,
|
|
36
|
+
) {
|
|
37
|
+
const featureId = feature._id
|
|
38
|
+
const change =
|
|
39
|
+
index === undefined
|
|
40
|
+
? new LocationStartChange({
|
|
41
|
+
typeName: 'LocationStartChange',
|
|
42
|
+
changedIds: [featureId],
|
|
43
|
+
featureId,
|
|
44
|
+
oldStart,
|
|
45
|
+
newStart,
|
|
46
|
+
assembly: feature.assemblyId,
|
|
47
|
+
})
|
|
48
|
+
: new DiscontinuousLocationStartChange({
|
|
49
|
+
typeName: 'DiscontinuousLocationStartChange',
|
|
50
|
+
changedIds: [featureId],
|
|
51
|
+
featureId,
|
|
52
|
+
oldStart,
|
|
53
|
+
newStart,
|
|
54
|
+
assembly: feature.assemblyId,
|
|
55
|
+
index,
|
|
56
|
+
})
|
|
57
|
+
return changeManager.submit(change)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function handleFeatureEndChange(
|
|
61
|
+
changeManager: ChangeManager,
|
|
62
|
+
feature: AnnotationFeatureI,
|
|
63
|
+
oldEnd: number,
|
|
64
|
+
newEnd: number,
|
|
65
|
+
index?: number,
|
|
66
|
+
) {
|
|
67
|
+
const featureId = feature._id
|
|
68
|
+
const change =
|
|
69
|
+
index === undefined
|
|
70
|
+
? new LocationEndChange({
|
|
71
|
+
typeName: 'LocationEndChange',
|
|
72
|
+
changedIds: [featureId],
|
|
73
|
+
featureId,
|
|
74
|
+
oldEnd,
|
|
75
|
+
newEnd,
|
|
76
|
+
assembly: feature.assemblyId,
|
|
77
|
+
})
|
|
78
|
+
: new DiscontinuousLocationEndChange({
|
|
79
|
+
typeName: 'DiscontinuousLocationEndChange',
|
|
80
|
+
changedIds: [featureId],
|
|
81
|
+
featureId,
|
|
82
|
+
oldEnd,
|
|
83
|
+
newEnd,
|
|
84
|
+
assembly: feature.assemblyId,
|
|
85
|
+
index,
|
|
86
|
+
})
|
|
87
|
+
return changeManager.submit(change)
|
|
88
|
+
}
|