@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,180 @@
|
|
|
1
|
+
import { openLocation } from '@jbrowse/core/util/io'
|
|
2
|
+
import equal from 'fast-deep-equal/es6'
|
|
3
|
+
import { IDBPDatabase, IDBPTransaction, openDB } from 'idb/with-async-ittr'
|
|
4
|
+
|
|
5
|
+
import { PREFIXED_ID_PATH, getWords } from './fulltext'
|
|
6
|
+
import {
|
|
7
|
+
OntologyDB,
|
|
8
|
+
isOntologyDBEdge,
|
|
9
|
+
isOntologyDBNode,
|
|
10
|
+
} from './indexeddb-schema'
|
|
11
|
+
import { GraphDocument } from './obo-graph-json-schema'
|
|
12
|
+
import OntologyStore from '.'
|
|
13
|
+
import { defaultTextIndexFields } from '..'
|
|
14
|
+
|
|
15
|
+
/** schema version we are currently on, used for the IndexedDB schema open call */
|
|
16
|
+
const schemaVersion = 2
|
|
17
|
+
|
|
18
|
+
export type Database = IDBPDatabase<OntologyDB>
|
|
19
|
+
|
|
20
|
+
/** open the IndexedDB and create the DB schema if necessary */
|
|
21
|
+
export async function openDatabase(this: OntologyStore, dbName: string) {
|
|
22
|
+
// await deleteDB(dbName) // uncomment this to reload every time during development
|
|
23
|
+
return openDB<OntologyDB>(dbName, schemaVersion, {
|
|
24
|
+
upgrade(
|
|
25
|
+
database: IDBPDatabase<OntologyDB>,
|
|
26
|
+
oldVersion: number,
|
|
27
|
+
newVersion: number | null,
|
|
28
|
+
transaction: IDBPTransaction<
|
|
29
|
+
OntologyDB,
|
|
30
|
+
ArrayLike<'nodes' | 'edges' | 'meta'>,
|
|
31
|
+
'versionchange'
|
|
32
|
+
>,
|
|
33
|
+
_event: IDBVersionChangeEvent,
|
|
34
|
+
): void {
|
|
35
|
+
if (oldVersion < schemaVersion) {
|
|
36
|
+
if (database.objectStoreNames.contains('meta')) {
|
|
37
|
+
database.deleteObjectStore('meta')
|
|
38
|
+
}
|
|
39
|
+
if (database.objectStoreNames.contains('nodes')) {
|
|
40
|
+
database.deleteObjectStore('nodes')
|
|
41
|
+
}
|
|
42
|
+
if (database.objectStoreNames.contains('edges')) {
|
|
43
|
+
database.deleteObjectStore('edges')
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!database.objectStoreNames.contains('meta')) {
|
|
47
|
+
database.createObjectStore('meta')
|
|
48
|
+
}
|
|
49
|
+
if (!database.objectStoreNames.contains('nodes')) {
|
|
50
|
+
database.createObjectStore('nodes', { keyPath: 'id' })
|
|
51
|
+
const nodes = transaction.objectStore('nodes')
|
|
52
|
+
nodes.createIndex('by-label', 'lbl')
|
|
53
|
+
nodes.createIndex('by-type', 'type')
|
|
54
|
+
nodes.createIndex('by-synonym', ['meta', 'synonyms', 'val'])
|
|
55
|
+
nodes.createIndex('full-text-words', 'fullTextWords', {
|
|
56
|
+
multiEntry: true,
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
if (!database.objectStoreNames.contains('edges')) {
|
|
60
|
+
database.createObjectStore('edges', { autoIncrement: true })
|
|
61
|
+
const edges = transaction.objectStore('edges')
|
|
62
|
+
edges.createIndex('by-subject', 'sub')
|
|
63
|
+
edges.createIndex('by-object', 'obj')
|
|
64
|
+
edges.createIndex('by-predicate', 'pred')
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** serialize all our words in the DB node so they can be indexed */
|
|
71
|
+
function serializeWords(foundWords: Iterable<[string, string]>): string[] {
|
|
72
|
+
const allWords = new Set<string>()
|
|
73
|
+
for (const [, word] of foundWords) {
|
|
74
|
+
allWords.add(word)
|
|
75
|
+
}
|
|
76
|
+
return [...allWords]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** load a OBO Graph JSON file into a database */
|
|
80
|
+
export async function loadOboGraphJson(this: OntologyStore, db: Database) {
|
|
81
|
+
const startTime = Date.now()
|
|
82
|
+
|
|
83
|
+
// TODO: using file streaming along with an event-based json parser
|
|
84
|
+
// instead of JSON.parse and .readFile could probably make this faster
|
|
85
|
+
// and less memory intensive
|
|
86
|
+
const oboGraph = JSON.parse(
|
|
87
|
+
await openLocation(this.sourceLocation).readFile('utf8'),
|
|
88
|
+
) as GraphDocument
|
|
89
|
+
|
|
90
|
+
const parseTime = Date.now()
|
|
91
|
+
|
|
92
|
+
const [graph, ...additionalGraphs] = oboGraph.graphs ?? []
|
|
93
|
+
if (!graph) {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
if (additionalGraphs.length > 0) {
|
|
97
|
+
throw new Error('multiple graphs not supported')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const tx = db.transaction(['meta', 'nodes', 'edges'], 'readwrite')
|
|
102
|
+
await tx.objectStore('meta').clear()
|
|
103
|
+
await tx.objectStore('nodes').clear()
|
|
104
|
+
await tx.objectStore('edges').clear()
|
|
105
|
+
|
|
106
|
+
// load nodes
|
|
107
|
+
const nodeStore = tx.objectStore('nodes')
|
|
108
|
+
const fullTextIndexPaths = getTextIndexFields
|
|
109
|
+
.call(this)
|
|
110
|
+
.map((def) => def.jsonPath)
|
|
111
|
+
for (const node of graph.nodes ?? []) {
|
|
112
|
+
if (isOntologyDBNode(node)) {
|
|
113
|
+
await nodeStore.add({
|
|
114
|
+
...node,
|
|
115
|
+
fullTextWords: serializeWords(
|
|
116
|
+
getWords(node, fullTextIndexPaths, this.prefixes),
|
|
117
|
+
),
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// load edges
|
|
123
|
+
const edgeStore = tx.objectStore('edges')
|
|
124
|
+
for (const edge of graph.edges ?? []) {
|
|
125
|
+
if (isOntologyDBEdge(edge)) {
|
|
126
|
+
await edgeStore.add(edge)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
await tx.done
|
|
131
|
+
|
|
132
|
+
// record some metadata about this ontology and load operation
|
|
133
|
+
const tx2 = db.transaction('meta', 'readwrite')
|
|
134
|
+
await tx2.objectStore('meta').add(
|
|
135
|
+
{
|
|
136
|
+
ontologyRecord: {
|
|
137
|
+
name: this.ontologyName,
|
|
138
|
+
version: this.ontologyVersion,
|
|
139
|
+
sourceLocation: this.sourceLocation,
|
|
140
|
+
},
|
|
141
|
+
storeOptions: this.options,
|
|
142
|
+
graphMeta: graph.meta,
|
|
143
|
+
timestamp: String(new Date()),
|
|
144
|
+
schemaVersion,
|
|
145
|
+
timings: {
|
|
146
|
+
overall: Date.now() - startTime,
|
|
147
|
+
load: Date.now() - parseTime,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
'meta',
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
await tx2.done
|
|
154
|
+
} catch (error) {
|
|
155
|
+
await db.transaction('meta', 'readwrite').objectStore('meta').clear()
|
|
156
|
+
throw error
|
|
157
|
+
}
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function getTextIndexFields(this: OntologyStore) {
|
|
162
|
+
return [
|
|
163
|
+
{ displayName: 'ID', jsonPath: PREFIXED_ID_PATH },
|
|
164
|
+
...(this.options.textIndexing?.indexFields ?? defaultTextIndexFields),
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export async function isDatabaseCurrent(this: OntologyStore, db: Database) {
|
|
169
|
+
// since metadata is loaded last, we use it as a signal that all the other data
|
|
170
|
+
// was loaded
|
|
171
|
+
const [meta] = await db.transaction('meta').objectStore('meta').getAll()
|
|
172
|
+
if (!meta) {
|
|
173
|
+
return false
|
|
174
|
+
}
|
|
175
|
+
// check that the index paths and prefixes are the same as our current ones
|
|
176
|
+
return (
|
|
177
|
+
equal(this.options.prefixes, meta.storeOptions?.prefixes) &&
|
|
178
|
+
equal(this.options.textIndexing, meta.storeOptions?.textIndexing)
|
|
179
|
+
)
|
|
180
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/** TS types for OBO Graph JSON (https://github.com/geneontology/obographs) */
|
|
2
|
+
// first generated with https://transform.tools/json-schema-to-typescript, then edited for conciseness
|
|
3
|
+
export interface GraphDocument {
|
|
4
|
+
'@context'?: unknown
|
|
5
|
+
meta?: Meta
|
|
6
|
+
graphs?: Graph[]
|
|
7
|
+
[k: string]: unknown
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Meta {
|
|
11
|
+
definition?: MetaDefinitionPropertyValue
|
|
12
|
+
comments?: string[]
|
|
13
|
+
subsets?: string[]
|
|
14
|
+
synonyms?: MetaSynonymPropertyValue[]
|
|
15
|
+
xrefs?: MetaXrefPropertyValue[]
|
|
16
|
+
basicPropertyValues?: MetaBasicPropertyValue[]
|
|
17
|
+
version?: string
|
|
18
|
+
deprecated?: boolean
|
|
19
|
+
[k: string]: unknown
|
|
20
|
+
}
|
|
21
|
+
export interface MetaDefinitionPropertyValue {
|
|
22
|
+
pred?: string
|
|
23
|
+
val?: string
|
|
24
|
+
xrefs?: string[]
|
|
25
|
+
meta?: Meta
|
|
26
|
+
[k: string]: unknown
|
|
27
|
+
}
|
|
28
|
+
export interface MetaSynonymPropertyValue {
|
|
29
|
+
synonymType?: string
|
|
30
|
+
pred?: string
|
|
31
|
+
val?: string
|
|
32
|
+
xrefs?: string[]
|
|
33
|
+
meta?: Meta
|
|
34
|
+
[k: string]: unknown
|
|
35
|
+
}
|
|
36
|
+
export interface MetaXrefPropertyValue {
|
|
37
|
+
lbl?: string
|
|
38
|
+
pred?: string
|
|
39
|
+
val?: string
|
|
40
|
+
xrefs?: string[]
|
|
41
|
+
meta?: Meta
|
|
42
|
+
[k: string]: unknown
|
|
43
|
+
}
|
|
44
|
+
export interface MetaBasicPropertyValue {
|
|
45
|
+
pred?: string
|
|
46
|
+
val?: string
|
|
47
|
+
xrefs?: string[]
|
|
48
|
+
meta?: Meta
|
|
49
|
+
[k: string]: unknown
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface Graph {
|
|
53
|
+
id?: string
|
|
54
|
+
lbl?: string
|
|
55
|
+
meta?: Meta
|
|
56
|
+
nodes?: Node[]
|
|
57
|
+
edges?: Edge[]
|
|
58
|
+
|
|
59
|
+
equivalentNodesSets?: AxiomEquivalentNodesSet[]
|
|
60
|
+
logicalDefinitionAxioms?: LogicalDefinitionAxiom[]
|
|
61
|
+
domainRangeAxioms?: DomainRangeAxiom[]
|
|
62
|
+
propertyChainAxioms?: PropertyChainAxiom[]
|
|
63
|
+
[k: string]: unknown
|
|
64
|
+
}
|
|
65
|
+
export interface Node {
|
|
66
|
+
id?: string
|
|
67
|
+
lbl?: string
|
|
68
|
+
type?: 'CLASS' | 'INDIVIDUAL' | 'PROPERTY'
|
|
69
|
+
meta?: Meta
|
|
70
|
+
[k: string]: unknown
|
|
71
|
+
}
|
|
72
|
+
export interface Edge {
|
|
73
|
+
sub?: string
|
|
74
|
+
pred?: string
|
|
75
|
+
obj?: string
|
|
76
|
+
meta?: Meta
|
|
77
|
+
[k: string]: unknown
|
|
78
|
+
}
|
|
79
|
+
export interface AxiomEquivalentNodesSet {
|
|
80
|
+
representativeNodeId?: string
|
|
81
|
+
nodeIds?: string[]
|
|
82
|
+
meta?: Meta
|
|
83
|
+
[k: string]: unknown
|
|
84
|
+
}
|
|
85
|
+
export interface LogicalDefinitionAxiom {
|
|
86
|
+
definedClassId?: string
|
|
87
|
+
genusIds?: string[]
|
|
88
|
+
restrictions?: AxiomExistentialRestrictionExpression[]
|
|
89
|
+
meta?: Meta
|
|
90
|
+
[k: string]: unknown
|
|
91
|
+
}
|
|
92
|
+
export interface AxiomExistentialRestrictionExpression {
|
|
93
|
+
propertyId?: string
|
|
94
|
+
fillerId?: string
|
|
95
|
+
[k: string]: unknown
|
|
96
|
+
}
|
|
97
|
+
export interface DomainRangeAxiom {
|
|
98
|
+
predicateId?: string
|
|
99
|
+
domainClassIds?: string[]
|
|
100
|
+
rangeClassIds?: string[]
|
|
101
|
+
allValuesFromEdges?: Edge[]
|
|
102
|
+
meta?: Meta
|
|
103
|
+
[k: string]: unknown
|
|
104
|
+
}
|
|
105
|
+
export interface PropertyChainAxiom {
|
|
106
|
+
predicateId?: string
|
|
107
|
+
chainPredicateIds?: string[]
|
|
108
|
+
meta?: Meta
|
|
109
|
+
[k: string]: unknown
|
|
110
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file contains stuff dealing with IRI prefixes used in ontologies.
|
|
3
|
+
*
|
|
4
|
+
* ```
|
|
5
|
+
* const prefixes = new Map(['GO:', 'http://long.url/GO_'])
|
|
6
|
+
*
|
|
7
|
+
* applyPrefixes('http://long.url/GO_1234345') // returns 'GO:1234345'
|
|
8
|
+
*
|
|
9
|
+
* expandPrefixes('GO:1234345') // returns 'http://long.url/GO_1234345'
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* compact the given URI using the given prefixes
|
|
15
|
+
*/
|
|
16
|
+
export function applyPrefixes(uri: string, prefixes: Map<string, string>) {
|
|
17
|
+
for (const [prefix, uriBase] of prefixes.entries()) {
|
|
18
|
+
if (uri.startsWith(uriBase)) {
|
|
19
|
+
return uri.replace(uriBase, prefix)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return uri
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* expand the given compacted URI using given prefixes
|
|
27
|
+
*/
|
|
28
|
+
export function expandPrefixes(uri: string, prefixes: Map<string, string>) {
|
|
29
|
+
for (const [prefix, uriBase] of prefixes.entries()) {
|
|
30
|
+
if (uri.startsWith(prefix)) {
|
|
31
|
+
return uri.replace(prefix, uriBase)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return uri
|
|
35
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { ConfigurationSchema } from '@jbrowse/core/configuration'
|
|
2
|
+
import {
|
|
3
|
+
BlobLocation,
|
|
4
|
+
LocalPathLocation,
|
|
5
|
+
UriLocation,
|
|
6
|
+
} from '@jbrowse/core/util/types/mst'
|
|
7
|
+
import { autorun } from 'mobx'
|
|
8
|
+
import { Instance, addDisposer, getSnapshot, types } from 'mobx-state-tree'
|
|
9
|
+
|
|
10
|
+
import OntologyStore, { OntologyStoreOptions } from './OntologyStore'
|
|
11
|
+
import { OntologyDBNode } from './OntologyStore/indexeddb-schema'
|
|
12
|
+
import { applyPrefixes, expandPrefixes } from './OntologyStore/prefixes'
|
|
13
|
+
|
|
14
|
+
export { isDeprecated } from './OntologyStore/indexeddb-schema'
|
|
15
|
+
|
|
16
|
+
export const OntologyRecordType = types
|
|
17
|
+
.model('OntologyRecord', {
|
|
18
|
+
name: types.string,
|
|
19
|
+
version: 'unversioned',
|
|
20
|
+
source: types.union(LocalPathLocation, UriLocation, BlobLocation),
|
|
21
|
+
options: types.frozen<OntologyStoreOptions>(),
|
|
22
|
+
})
|
|
23
|
+
.volatile((_self) => ({
|
|
24
|
+
dataStore: undefined as undefined | OntologyStore,
|
|
25
|
+
}))
|
|
26
|
+
.actions((self) => ({
|
|
27
|
+
/** does nothing, just used to access the model to force its lifecycle hooks to run */
|
|
28
|
+
ping() {
|
|
29
|
+
return
|
|
30
|
+
},
|
|
31
|
+
initDataStore() {
|
|
32
|
+
self.dataStore = new OntologyStore(
|
|
33
|
+
self.name,
|
|
34
|
+
self.version,
|
|
35
|
+
getSnapshot(self.source),
|
|
36
|
+
self.options,
|
|
37
|
+
)
|
|
38
|
+
},
|
|
39
|
+
afterCreate() {
|
|
40
|
+
addDisposer(
|
|
41
|
+
self,
|
|
42
|
+
autorun(() => {
|
|
43
|
+
this.initDataStore()
|
|
44
|
+
}),
|
|
45
|
+
)
|
|
46
|
+
},
|
|
47
|
+
}))
|
|
48
|
+
|
|
49
|
+
export const OntologyManagerType = types
|
|
50
|
+
.model('OntologyManager', {
|
|
51
|
+
// create, update, and delete ontologies
|
|
52
|
+
ontologies: types.array(OntologyRecordType),
|
|
53
|
+
prefixes: types.optional(types.map(types.string), {
|
|
54
|
+
'GO:': 'http://purl.obolibrary.org/obo/GO_',
|
|
55
|
+
'SO:': 'http://purl.obolibrary.org/obo/SO_',
|
|
56
|
+
}),
|
|
57
|
+
})
|
|
58
|
+
.views((self) => ({
|
|
59
|
+
/**
|
|
60
|
+
* gets the OntologyRecord for the ontology we should be
|
|
61
|
+
* using for feature types (e.g. SO or maybe biotypes)
|
|
62
|
+
**/
|
|
63
|
+
get featureTypeOntology() {
|
|
64
|
+
// TODO: change this to read some configuration for which feature type ontology
|
|
65
|
+
// we should be using. currently hardcoded to use SO.
|
|
66
|
+
return this.findOntology('Sequence Ontology')
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
findOntology(name: string, version?: string) {
|
|
70
|
+
return self.ontologies.find((record) => {
|
|
71
|
+
return (
|
|
72
|
+
record.name === name &&
|
|
73
|
+
(version === undefined || record.version === version)
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
},
|
|
77
|
+
openOntology(name: string, version?: string) {
|
|
78
|
+
return this.findOntology(name, version)?.dataStore
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* compact the given URI using the currently configured
|
|
82
|
+
* prefixes
|
|
83
|
+
*/
|
|
84
|
+
applyPrefixes(uri: string) {
|
|
85
|
+
return applyPrefixes(uri, self.prefixes)
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* expand the given compacted URI using the currently
|
|
89
|
+
* configured prefixes
|
|
90
|
+
*/
|
|
91
|
+
expandPrefixes(uri: string) {
|
|
92
|
+
return expandPrefixes(uri, self.prefixes)
|
|
93
|
+
},
|
|
94
|
+
}))
|
|
95
|
+
.actions((self) => ({
|
|
96
|
+
addOntology(
|
|
97
|
+
name: string,
|
|
98
|
+
version: string,
|
|
99
|
+
source: Instance<typeof LocalPathLocation> | Instance<typeof UriLocation>,
|
|
100
|
+
options?: OntologyStoreOptions,
|
|
101
|
+
) {
|
|
102
|
+
const newlen = self.ontologies.push({
|
|
103
|
+
name,
|
|
104
|
+
version,
|
|
105
|
+
source,
|
|
106
|
+
options: { prefixes: new Map(self.prefixes.entries()), ...options },
|
|
107
|
+
})
|
|
108
|
+
// access it immediately to fire its lifecycle hooks
|
|
109
|
+
// (see https://github.com/mobxjs/mobx-state-tree/issues/1665)
|
|
110
|
+
self.ontologies[newlen - 1].ping()
|
|
111
|
+
},
|
|
112
|
+
}))
|
|
113
|
+
|
|
114
|
+
export default OntologyManagerType
|
|
115
|
+
|
|
116
|
+
export interface TextIndexFieldDefinition {
|
|
117
|
+
/** name to display in the UI for text taken from this field or fields */
|
|
118
|
+
displayName: string
|
|
119
|
+
/** JSONPath of the field(s) */
|
|
120
|
+
jsonPath: string
|
|
121
|
+
}
|
|
122
|
+
export const defaultTextIndexFields: TextIndexFieldDefinition[] = [
|
|
123
|
+
{ displayName: 'Label', jsonPath: '$.lbl' },
|
|
124
|
+
{ displayName: 'Synonym', jsonPath: '$.meta.synonyms[*].val' },
|
|
125
|
+
{ displayName: 'Definition', jsonPath: '$.meta.definition.val' },
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
export const OntologyRecordConfiguration = ConfigurationSchema(
|
|
129
|
+
'OntologyRecord',
|
|
130
|
+
{
|
|
131
|
+
name: {
|
|
132
|
+
type: 'string',
|
|
133
|
+
description: 'the full name of the ontology, e.g. "Gene Ontology"',
|
|
134
|
+
defaultValue: 'My Ontology',
|
|
135
|
+
},
|
|
136
|
+
version: {
|
|
137
|
+
type: 'string',
|
|
138
|
+
description: "the ontology's version string",
|
|
139
|
+
defaultValue: 'unversioned',
|
|
140
|
+
},
|
|
141
|
+
source: {
|
|
142
|
+
type: 'fileLocation',
|
|
143
|
+
description: "the download location for the ontology's source file",
|
|
144
|
+
defaultValue: {
|
|
145
|
+
locationType: 'UriLocation',
|
|
146
|
+
uri: 'http://example.com/myontology.json',
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
textIndexFields: {
|
|
150
|
+
type: 'frozen',
|
|
151
|
+
description:
|
|
152
|
+
'JSON paths for text fields that will be indexed for text searching',
|
|
153
|
+
defaultValue: defaultTextIndexFields,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
export type OntologyManager = Instance<typeof OntologyManagerType>
|
|
159
|
+
export type OntologyRecord = Instance<typeof OntologyRecordType>
|
|
160
|
+
|
|
161
|
+
export type OntologyTerm = OntologyDBNode
|
|
162
|
+
|
|
163
|
+
export type OntologyClass = OntologyTerm & { type: 'CLASS' }
|
|
164
|
+
export function isOntologyClass(term: OntologyTerm): term is OntologyClass {
|
|
165
|
+
return term.type === 'CLASS'
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export type OntologyProperty = OntologyTerm & { type: 'PROPERTY' }
|
|
169
|
+
export function isOntologyProperty(
|
|
170
|
+
term: OntologyTerm,
|
|
171
|
+
): term is OntologyProperty {
|
|
172
|
+
return term.type === 'PROPERTY'
|
|
173
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TrackLines'
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
}
|