Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feedback ontology loading #482

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Next Next commit
Load ontology synonyms into state tree
  • Loading branch information
garrettjstevens committed Nov 12, 2024
commit 51b1dedca798697fb7ade8701fd5fd6a6c0b4442

This file was deleted.

Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ import { addDisposer, isAlive } from 'mobx-state-tree'

import { ApolloSessionModel } from '../../session'
import { baseModelFactory } from './base'
import { getGlyph } from './getGlyph'
import { boxGlyph, geneGlyph, genericChildGlyph } from '../glyphs'

export function layoutsModelFactory(
pluginManager: PluginManager,
@@ -60,6 +60,48 @@ export function layoutsModelFactory(
return
})
},
getGlyph(feature: AnnotationFeature) {
if (this.looksLikeGene(feature)) {
return geneGlyph
}
if (feature.children?.size) {
return genericChildGlyph
}
return boxGlyph
},
looksLikeGene(feature: AnnotationFeature): boolean {
const { featureTypeOntology } =
self.session.apolloDataStore.ontologyManager
if (!featureTypeOntology) {
return false
}
const { children } = feature
if (!children?.size) {
return false
}
const isGene = featureTypeOntology.isTypeOf(feature.type, 'gene')
if (!isGene) {
return false
}
for (const [, child] of children) {
if (featureTypeOntology.isTypeOf(child.type, 'mRNA')) {
const { children: grandChildren } = child
if (!grandChildren?.size) {
return false
}
const hasCDS = [...grandChildren.values()].some((grandchild) =>
featureTypeOntology.isTypeOf(grandchild.type, 'CDS'),
)
const hasExon = [...grandChildren.values()].some((grandchild) =>
featureTypeOntology.isTypeOf(grandchild.type, 'exon'),
)
if (hasCDS && hasExon) {
return true
}
}
}
return false
},
}))
.actions((self) => ({
addSeenFeature(feature: AnnotationFeature) {
@@ -94,10 +136,9 @@ export function layoutsModelFactory(
) {
continue
}
const rowCount = getGlyph(feature).getRowCount(
feature,
self.lgv.bpPerPx,
)
const rowCount = self
.getGlyph(feature)
.getRowCount(feature, self.lgv.bpPerPx)
let startingRow = 0
let placed = false
while (!placed) {
@@ -174,10 +215,9 @@ export function layoutsModelFactory(
}
}
if (layoutFeature.hasDescendant(feature._id)) {
const row = getGlyph(layoutFeature).getRowForFeature(
layoutFeature,
feature,
)
const row = self
.getGlyph(layoutFeature)
.getRowForFeature(layoutFeature, feature)
if (row !== undefined) {
return {
layoutIndex: idx,
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@ import type { CSSProperties } from 'react'
import { Coord } from '../components'
import { Glyph } from '../glyphs/Glyph'
import { CanvasMouseEvent } from '../types'
import { getGlyph } from './getGlyph'
import { renderingModelFactory } from './rendering'
import { Frame, getFrame } from '@jbrowse/core/util'

@@ -147,7 +146,7 @@ export function mouseEventsModelIntermediateFactory(
return mousePosition
}
const [featureRow, topLevelFeature] = foundFeature
const glyph = getGlyph(topLevelFeature)
const glyph = self.getGlyph(topLevelFeature)
const feature = glyph.getFeatureFromLayout(
topLevelFeature,
bp,
@@ -323,7 +322,7 @@ export function mouseEventsModelFactory(
return []
}
const { topLevelFeature } = apolloHover
const glyph = getGlyph(topLevelFeature)
const glyph = self.getGlyph(topLevelFeature)
return glyph.getContextMenuItems(self)
},
}))
@@ -483,7 +482,9 @@ export function mouseEventsModelFactory(
if (apolloDragging) {
// NOTE: the glyph where the drag started is responsible for drawing the preview.
// it can call methods in other glyphs to help with this though.
const glyph = getGlyph(apolloDragging.feature.topLevelFeature)
const glyph = self.getGlyph(
apolloDragging.feature.topLevelFeature,
)
glyph.drawDragPreview(self, ctx)
}
},
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ import { autorun } from 'mobx'
import { Instance, addDisposer } from 'mobx-state-tree'

import { ApolloSessionModel } from '../../session'
import { getGlyph } from './getGlyph'
import { layoutsModelFactory } from './layouts'

export function renderingModelIntermediateFactory(
@@ -428,7 +427,7 @@ export function renderingModelFactory(
) {
continue
}
getGlyph(feature).draw(ctx, feature, row, self, idx)
self.getGlyph(feature).draw(ctx, feature, row, self, idx)
}
}
}
46 changes: 45 additions & 1 deletion packages/jbrowse-plugin-apollo/src/OntologyManager/index.ts
Original file line number Diff line number Diff line change
@@ -5,7 +5,13 @@
UriLocation,
} from '@jbrowse/core/util/types/mst'
import { autorun } from 'mobx'
import { Instance, addDisposer, getSnapshot, types } from 'mobx-state-tree'
import {
Instance,
addDisposer,
flow,
getSnapshot,
types,
} from 'mobx-state-tree'

import OntologyStore, { OntologyStoreOptions } from './OntologyStore'
import { OntologyDBNode } from './OntologyStore/indexeddb-schema'
@@ -19,6 +25,7 @@
version: 'unversioned',
source: types.union(LocalPathLocation, UriLocation, BlobLocation),
options: types.frozen<OntologyStoreOptions>(),
equivalentTypes: types.map(types.array(types.string)),
})
.volatile((_self) => ({
dataStore: undefined as undefined | OntologyStore,
@@ -44,6 +51,43 @@
}),
)
},
setEquivalentTypes(type: string, equivalentTypes: string[]) {
self.equivalentTypes.set(type, equivalentTypes)
},
}))
.actions((self) => ({
loadEquivalentTypes: flow(function* loadEquivalentTypes(type: string) {
if (!self.dataStore) {
return
}
const terms = (yield self.dataStore.getTermsWithLabelOrSynonym(
type,
)) as unknown as OntologyTerm[]
const equivalents: string[] = terms
.map((term) => term.lbl)
.filter((term) => term != undefined)
console.log('loading', type, equivalents)

Check warning on line 69 in packages/jbrowse-plugin-apollo/src/OntologyManager/index.ts

GitHub Actions / Lint

Unexpected console statement
self.setEquivalentTypes(type, equivalents)
}),
}))
.views((self) => ({
isTypeOf(queryType: string, typeOf: string): boolean {
if (queryType === typeOf) {
return true
}
if (!self.dataStore) {
return false
}
const equivalents = self.equivalentTypes.get(typeOf)
if (!equivalents) {
void self.loadEquivalentTypes(typeOf)
return false
}
if (equivalents.includes(queryType)) {
return true
}
return false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return equivalents.includes(queryType)

},
}))

export const OntologyManagerType = types
Original file line number Diff line number Diff line change
@@ -21,7 +21,6 @@ import { FeatureAttributes } from './FeatureAttributes'
import { featureContextMenuItems } from './featureContextMenuItems'
import type { ContextMenuState } from './HybridGrid'
import { NumberCell } from './NumberCell'
import { getGlyph } from '../../LinearApolloDisplay/stateModel/getGlyph'

const useStyles = makeStyles()((theme) => ({
typeContent: {
@@ -134,7 +133,7 @@ export const Feature = observer(function Feature({
displayState.setApolloHover({
feature,
topLevelFeature: getTopLevelFeature(feature),
glyph: getGlyph(getTopLevelFeature(feature)),
glyph: displayState.getGlyph(getTopLevelFeature(feature)),
})
}}
className={