Skip to content

Commit

Permalink
filter features by type
Browse files Browse the repository at this point in the history
  • Loading branch information
shashankbrgowda committed Oct 21, 2024
1 parent 1b5f940 commit c6bfa7a
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import { getParentRenderProps } from '@jbrowse/core/util/tracks'
// import type LinearGenomeViewPlugin from '@jbrowse/plugin-linear-genome-view'
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
import { autorun } from 'mobx'
import { addDisposer, getRoot, types } from 'mobx-state-tree'
import { addDisposer, cast, getRoot, types, getSnapshot } from 'mobx-state-tree'

import { ApolloInternetAccountModel } from '../../ApolloInternetAccount/model'
import { ApolloSessionModel } from '../../session'
import { ApolloRootModel } from '../../types'
import { TrackHeightMixin } from './trackHeightMixin'
import { FilterFeatures } from '../../components/FilterFeatures'

export function baseModelFactory(
_pluginManager: PluginManager,
Expand All @@ -43,6 +44,7 @@ export function baseModelFactory(
configuration: ConfigurationReference(configSchema),
graphical: true,
table: true,
filteredFeatureTypes: types.optional(types.array(types.string), ['gene']),
})
.volatile((self) => ({
lgv: getContainingView(self) as unknown as LinearGenomeViewModel,
Expand Down Expand Up @@ -126,6 +128,9 @@ export function baseModelFactory(
get showTable() {
return self.table
},
get getFilteredFeatureTypes() {
return self.filteredFeatureTypes
},
}))
.actions((self) => ({
showGraphicalOnly() {
Expand All @@ -140,6 +145,9 @@ export function baseModelFactory(
self.graphical = true
self.table = true
},
updateFilteredFeatureTypes(types: string[]) {
self.filteredFeatureTypes = cast(types)
},
}))
.views((self) => {
const { trackMenuItems: superTrackMenuItems } = self
Expand Down Expand Up @@ -175,6 +183,28 @@ export function baseModelFactory(
self.showGraphicalAndTable()
},
},
{
label: 'Filter features by type',
onClick: () => {
const session = self.session as unknown as ApolloSessionModel
;(self.session as unknown as AbstractSessionModel).queueDialog(
(doneCallback) => [
FilterFeatures,
{
session,
handleClose: () => {
doneCallback()
},
// eslint-disable-next-line unicorn/consistent-destructuring
featureTypes: getSnapshot(self.filteredFeatureTypes),
onUpdate: (types: string[]) => {
self.updateFilteredFeatureTypes(types)
},
},
],
)
},
},
]
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ export function layoutsModelFactory(
feature.min,
feature.max,
) &&
!self.seenFeatures.has(feature._id)
!self.seenFeatures.has(feature._id) &&
self.filteredFeatureTypes &&
self.filteredFeatureTypes.includes(feature.type)
) {
self.addSeenFeature(feature)
}
Expand Down
118 changes: 118 additions & 0 deletions packages/jbrowse-plugin-apollo/src/components/FilterFeatures.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, { useState } from 'react'
import { ApolloSessionModel } from '../session'
import { Dialog } from './Dialog'
import {
Box,
Button,
Chip,
DialogContent,
DialogContentText,
Grid,
TextField,
} from '@mui/material'
import { isOntologyClass } from '../OntologyManager'
import { OntologyTermAutocomplete } from './OntologyTermAutocomplete'
import { observer } from 'mobx-react'

interface FilterFeaturesProps {
onUpdate: (types: string[]) => void
featureTypes: string[]
handleClose: () => void
session: ApolloSessionModel
}

export const FilterFeatures = observer(function FilterFeatures({
featureTypes,
handleClose,
onUpdate,
session,
}: FilterFeaturesProps) {
const [type, setType] = useState('')
const [selectedFeatureTypes, setSelectedFeatureTypes] =
useState<string[]>(featureTypes)
const handleChange = (value: string): void => {
setType(value)
}
const handleAddFeatureType = () => {
if (type) {
if (selectedFeatureTypes.includes(type)) {
return
}
onUpdate([...selectedFeatureTypes, type])
setSelectedFeatureTypes([...selectedFeatureTypes, type])
}
}
const handleFeatureTypeDelete = (value: string) => {
const newTypes = selectedFeatureTypes.filter((type) => type !== value)
onUpdate(newTypes)
setSelectedFeatureTypes(newTypes)
}

return (
<Dialog
open
maxWidth={false}
data-testid="filter-features-dialog"
title="Filter features by type"
handleClose={handleClose}
>
<DialogContent>
<DialogContentText>
Select the feature types you want to display in the apollo track
</DialogContentText>
<Grid container spacing={2}>
<Grid item xs={7}>
<OntologyTermAutocomplete
session={session}
ontologyName="Sequence Ontology"
style={{ width: '100%' }}
value={type}
filterTerms={isOntologyClass}
renderInput={(params) => (
<TextField
{...params}
label="Feature type"
variant="outlined"
fullWidth
/>
)}
onChange={(oldValue, newValue) => {
if (newValue) {
handleChange(newValue)
}
}}
/>
</Grid>
<Grid item xs={5}>
<Button
variant="contained"
onClick={handleAddFeatureType}
disabled={!type}
style={{ marginTop: 9 }}
size="medium"
>
Add
</Button>
</Grid>
</Grid>
{selectedFeatureTypes.length > 0 && (
<div style={{ width: 300 }}>
<hr />
<DialogContentText>Selected feature types:</DialogContentText>
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
{selectedFeatureTypes.map((value) => (
<Chip
key={value}
label={value}
onDelete={() => {
handleFeatureTypeDelete(value)
}}
/>
))}
</Box>
</div>
)}
</DialogContent>
</Dialog>
)
})

0 comments on commit c6bfa7a

Please sign in to comment.